Get rectangular block in matlab - matlab

For my project I need to get features for negative samples to train the classifier. I already had positive samples. Here is what I am trying to do.
root_dir = '/home/shahnawaz/Downloads/test';
data_set = 'training';
%% get label directory
cam = 2; % 2 = left color camera
label_dir = fullfile(root_dir,[data_set '/label_' num2str(cam)]);
nlabels = length(dir(fullfile(label_dir, '*.txt')));
%% main loop
img_idx=0;
count = 1;
for lab_idx = 1:1:nlabels
objects = readLabels(label_dir,lab_idx-1);
for a = 1 :1:length(objects)
s1 = objects(a).type;
s2 = 'Car';
cmp = strcmp(s1,s2);
rear = (objects(a).alpha >= -pi/2+0.07) | (objects(a).alpha <=-pi/2-0.07); % get car with rear portion
if (cmp )
%% write your code.
end
end
end
EDIT:
I have 7481 images with a resolution of 1224 * 370 and corresponding label files(annotation of objects in the image). From the label I get width = 423.81 - 387.63 = 37 and height = 203.12 - 181.54 = 22. I want to get a similar block excluding points 423.81 - 387.63 = 37 and 203.12 - 181.54 = 22 . Can someone help me do that. Here is the structure of the label file.
Truck 0.00 0 -1.57 599.41 156.40 629.75 189.25 2.85 2.63 12.34 0.47 1.49 69.44 -1.56
Car 0.00 0 1.85 387.63 181.54 423.81 203.12 1.67 1.87 3.69 -16.53 2.39 58.49 1.57
Cyclist 0.00 3 -1.65 676.60 163.95 688.98 193.93 1.86 0.60 2.02 4.59 1.32 45.84 -1.55
DontCare -1 -1 -10 503.89 169.71 590.61 190.13 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 511.35 174.96 527.81 187.45 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 532.37 176.35 542.68 185.27 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 559.62 175.83 575.40 183.15 -1 -1 -1 -1000 -1000 -1000 -10
EDIT: I also have label file where I have more than one 'Car' object and where there is no 'Car' object. It is confusing me. Can some one sketch pseudo code
The 15 columns represent:
#Values Name Description
----------------------------------------------------------------------------
1 type Describes the type of object: 'Car', 'Van', 'Truck',
'Pedestrian', 'Person_sitting', 'Cyclist', 'Tram',
'Misc' or 'DontCare'
1 truncated Float from 0 (non-truncated) to 1 (truncated), where
truncated refers to the object leaving image boundaries
1 occluded Integer (0,1,2,3) indicating occlusion state:
0 = fully visible, 1 = partly occluded
2 = largely occluded, 3 = unknown
1 alpha Observation angle of object, ranging [-pi..pi]
4 bbox 2D bounding box of object in the image (0-based index):
contains left, top, right, bottom pixel coordinates
3 dimensions 3D object dimensions: height, width, length (in meters)
3 location 3D object location x,y,z in camera coordinates (in meters)
1 rotation_y Rotation ry around Y-axis in camera coordinates [-pi..pi]
1 score Only for results: Float, indicating confidence in
detection, needed for p/r curves, higher is better.

Related

How to calculate weighted (grayscale) centroids of pixel clusters contained within bounding boxes on an image

I've written some code in MATLAB that converts an image (of stars) into a grayscale image and then into a binary image using a set threshold and then labels each cluster of pixels (stars) that is above this threshold. The labelling produces an output:
e.g.
[1 1 1 0 0 0 0 0 0
1 1 0 0 0 2 2 2 0
0 0 0 3 3 0 2 0 0
0 0 0 3 3 0 0 0 0]
So each cluster of 1's, 2's, 3's etc. represents a star. After this the code then finds the centroids of each pixel cluster and draws a bounding box around each centroid (centered on the centroid) with an 8 x 8 pixel area. The bounding box limits are made by finding xmax, xmin, ymax, ymin of each calculated centroid, which involves either adding or subtracting 4 (pixels) from the x and y coordinates of each centroid.
The weighted centroid is calculated like so:
x_coordinate_centroid = sum(x_coordinate .* pixel_values) / sum_pixel_values
y_coordinate_centroid = sum(y_coordinate .* pixel_values) / sum_pixel_values
x/y_coordinate and pixel values are for the pixels contained within each bounding box.
The bounding box would surround an 8 x 8 pixel area (with the given intensities) on the grayscale image such as:
[100 100 100 90 20 20 0 0
80 90 100 90 20 30 0 0
50 70 100 70 30 0 20 0
50 0 0 60 30 30 0 0
0 0 0 0 0 0 0 0
0 50 0 0 0 0 0 0
0 40 0 0 0 0 0 0
0 20 0 0 0 0 0 0]
The top left value ([xmin, ymax]), for example, could have image coordinates [41, 14] and an intensity of 100.
The output from my code, for example, could give 5 bounding boxes across the grayscale image. I now need to write code that automatically calculates the weighted centroid of each bounding box region. I'm not sure how to go about this, does anyone have any ideas how this can be achieved?
My code for calculating the centroids and their bounding boxes is shown below.
%% Calculate centroids of each labelled pixel cluster within binary image
N = max(B(:)); % total number of pixel labels generated in output array
sum_total = zeros(N,1); % create N x 1 array of 0's
sum_yv = zeros(N,1); % "
sum_xv = zeros(N,1); % "
for xx=1:size(B,2) % search through y positions
for yy=1:size(B,1) % search through x positions
index = B(yy,xx);
if index>0
sum_total(index) = sum_total(index) + 1;
sum_yv(index) = sum_yv(index) + yy;
sum_xv(index) = sum_xv(index) + xx;
end
end
end
centroids = [sum_xv, sum_yv] ./ sum_total; % calculates centroids for each cluster
x_lower_limits = centroids(:,1)-4;
y_lower_limits = centroids(:,2)+4; % lower on image means larger y coord number
x_upper_limits = centroids(:,1)+4;
y_upper_limits = centroids(:,2)-4; % higher on image means lower y coord number
x_lower_limits(x_lower_limits<1)=1; % limit smallest x coord to image axis (1,y)
y_lower_limits(y_lower_limits>size(binary_image,1))=size(binary_image,1); % limit largest y coord to image axis (x,517)
x_upper_limits(x_upper_limits>size(binary_image,2))=size(binary_image,2); % limit largest x coord to image axis (508,y)
y_upper_limits(y_upper_limits<1)=1; % limit smallest y coord to image axis (x,1)
width = x_upper_limits(:,1) - x_lower_limits(:,1); % width of bounding box
height = y_lower_limits(:,1) - y_upper_limits(:,1); % height of bounding box
hold on
for xl=1:size(x_lower_limits,1)
r(xl)=rectangle('Position',[x_lower_limits(xl,1) y_upper_limits(xl,1) width(xl,1) height(xl,1)],'EdgeColor','r');
end
for i=1:size(centroids,1)
plot(centroids(i,1),centroids(i,2),'rx','MarkerSize',10)
end
hold off
%%

How do I calculate the area of a 3 dimensional projection?

For example, using the following code, I have a coordinate matrix with 3 cubical objects defined by 8 corners each, for a total of 24 coordinates. I apply a rotation to my coordinates, then delete the y coordinate to obtain a projection in the x-z plane. How do I calculate the area of these cubes in the x-z plane, ignoring gaps and accounting for overlap? I have tried using polyarea, but this doesn't seem to work.
clear all
clc
A=[-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 52
20 0 5
20 0 5
-100 50 5
-100 50 5
20 50 52
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0]; %3 Buildings Coordinate Matrix
theta=60; %Angle
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1]; %Rotation matrix
R=A*rota; %rotates the matrix
R(:,2)=[];%deletes the y column
The first step will be to use convhull (as yar suggests) to get an outline of each projected polygonal region. It should be noted that a convex hull is appropriate to use here since you are dealing with cuboids, which are convex objects. I think you have an error in the coordinates for your second cuboid (located in A(9:16, :)), so I modified your code to the following:
A = [-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 5
20 0 52
20 0 5
-100 50 5
-100 50 52
20 50 5
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0];
theta = 60;
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];
R = A*rota;
And you can generate the polygonal outlines and visualize them like so:
nPerPoly = 8;
nPoly = size(R, 1)/nPerPoly;
xPoly = mat2cell(R(:, 1), nPerPoly.*ones(1, nPoly));
zPoly = mat2cell(R(:, 3), nPerPoly.*ones(1, nPoly));
C = cell(1, nPoly);
for iPoly = 1:nPoly
P = convhull(xPoly{iPoly}, zPoly{iPoly});
xPoly{iPoly} = xPoly{iPoly}(P);
zPoly{iPoly} = zPoly{iPoly}(P);
C{iPoly} = P([1:end-1; 2:end].')+nPerPoly.*(iPoly-1); % Constrained edges, needed later
end
figure();
colorOrder = get(gca, 'ColorOrder');
nColors = size(colorOrder, 1);
for iPoly = 1:nPoly
faceColor = colorOrder(rem(iPoly-1, nColors)+1, :);
patch(xPoly{iPoly}, zPoly{iPoly}, faceColor, 'EdgeColor', faceColor, 'FaceAlpha', 0.6);
hold on;
end
axis equal;
axis off;
And here's the plot:
If you wanted to calculate the area of each polygonal projection and add them up it would be very easy: just change the above loop to capture and sum the second output from the calls to convexhull:
totalArea = 0;
for iPoly = 1:nPoly
[~, cuboidArea] = convhull(xPoly{iPoly}, zPoly{iPoly});
totalArea = totalArea+cuboidArea;
end
However, if you want the area of the union of the polygons, you have to account for the overlap. You have a few alternatives. If you have the Mapping Toolbox then you could use the function polybool to get the outline, then use polyarea to compute its area. There are also utilities you can find on the MathWorks File Exchange (such as this and this). I'll show you another alternative here that uses delaunayTriangulation. First we can take the edge constraints C created above to use when creating a triangulation of the projected points:
oldState = warning('off', 'all');
DT = delaunayTriangulation(R(:, [1 3]), vertcat(C{:}));
warning(oldState);
This will automatically create new vertices where the constrained edges intersect. Unfortunately, it will also perform the triangulation on the convex hull of all the points, filling in spots that we don't want filled. Here's what the triangulation looks like:
figure();
triplot(DT, 'Color', 'k');
axis equal;
axis off;
We now have to identify the extra triangles we don't want and remove them. We can do this by finding the centroids of each triangle and using inpolygon to test if they are outside all 3 of our individual cuboid projections. We can then compute the areas of the remaining triangles and sum them up using polyarea, giving us the total area of the projection:
dtFaces = DT.ConnectivityList;
dtVertices = DT.Points;
meanX = mean(reshape(dtVertices(dtFaces, 1), size(dtFaces)), 2);
meanZ = mean(reshape(dtVertices(dtFaces, 2), size(dtFaces)), 2);
index = inpolygon(meanX, meanZ, xPoly{1}, zPoly{1});
for iPoly = 2:nPoly
index = index | inpolygon(meanX, meanZ, xPoly{iPoly}, zPoly{iPoly});
end
dtFaces = dtFaces(index, :);
xUnion = reshape(dtVertices(dtFaces, 1), size(dtFaces)).';
yUnion = reshape(dtVertices(dtFaces, 2), size(dtFaces)).';
totalArea = sum(polyarea(xUnion, yUnion));
And the total area for this example is:
totalArea =
9.970392341143055e+03
NOTE: The above code has been generalized for an arbitrary number of cuboids.
polyarea is the right way to go, but you need to call it on the convex hull of each projection. If not, you will have points in the centers of your projections and the result is not a "simple" polygon.

stress and strain curve with Lammps

I want to try to draw stress and strain curve for copper nanoparticles with Lammps.
This is my code.
I don't know whether this is correct or not.
Can anybody help me?
It has fix nve for relaxation, but before that has fix nvt ,and these 2 fixes can't come together.
# tensile test
echo both
dimension 3
boundary s p p
units metal
atom_style atomic
##########create box#######
region copperbox block -80 80 -40 40 -40 40 units box
create_box 1 copperbox
lattice fcc 3.61
region copper block -60 60 -20 20 -20 20 units box
create_atoms 1 region copper
mass 1 63.546
thermo_modify lost ignore
region left block -60 -50 -20 20 -20 20 units box
group left region left
region right block 50 60 -20 20 -20 20 units box
group right region right
group middle subtract all left right
timestep 0.002
pair_style eam
pair_coeff * * cu_u3.eam
velocity all create 300 4928459 mom yes rot yes dist uniform
velocity left create 0 4928459 mom yes rot yes dist uniform
velocity right create 0 4928459 mom yes rot yes dist uniform
fix 1 all nvt temp 300 300 0.01
fix 2 left setforce 0 0 0
fix 3 right setforce 0 0 0
fix 4 all nve
thermo 100
run 1000
#####################################
compute 1 middle stress/atom
compute 2 middle reduce sum c_1[1]
dump 1 all custom 100 stress.txt mass x y z c_1[1] c_1[2] c_1[3]
c_1[4] c_1[5] c_1[6]
dump 2 all xyz 100 dump.xyz
#####################################
variable a loop 2
label loopa
fix 8 right move linear 0.2 0 0 units box
fix 9 left move linear 0 0 0 units box
run 1000
#####################################
unfix 8
unfix 9
fix 8 right move linear 0 0 0 units box
fix 9 left move linear 0 0 0 units box
run 40000
#####################################
fix 10 all nve
thermo 100
run 10000
#####################################
variable sigma equal "c_2/(40000)*(10^4)"
variable l2 equal xcm(right,x)
variable l0 equal ${l2}
variable strain equal "(v_l2-v_l0)/(v_l0)*100"
next a
jump in.copper99 loopa
restart 1000 restart.*

Plot Zero Value on Contour Plot in MATLAB

I'm plotting z values, 0 to 10, on a contour plot.
When I include data 1 or greater, I obtain a contour plot. Like the following:
longitude = [80 82 95]
latitude = [30 32 35]
temp = [1 4 6; 1 2 7; 3 5 7]
contourf(longitude,latitude,temp)
Now, I want to plot the ZERO VALUE also on the contour plot. While I was expecting one color representing the zero value, instead I obtained a white square.
longitude = [80 82 95]
latitude = [30 32 35]
temp = [0 0 0; 0 0 0; 0 0 0]
contourf(longitude,latitude,temp)
Thanks a lot,
Amanda
As Issac mentioned. To plot a constant data in a contourf is not possible.
When you try to do so you will obtain this warning from Matlab:
temp =
0 0 0
0 0 0
0 0 0
Warning: Contour not rendered for constant ZData
> In contourf>parseargs at 458
In contourf at 63
In TESTrandom at 45
However, if you put some numbers as 0, the contourf works fine:
longitude = [80 82 95];
latitude = [30 32 35];
temp = [0 4 6; 1 0 7; 0 5 9];
contourf(longitude,latitude,temp);
hcb = colorbar('horiz'); % colour bar
set(get(hcb,'Xlabel'),'String','Contourf Bar.')

Making a static legend, independent of the actual plot

I'm plotting two surfaces in Matlab, the ground level which is constant and the water level which is changing in time.
I use an if statement to change the colormap of the water with increasing depth, determined by two thresholds (in the code below the thresholds are represented by the array C)
if max(C(:)) < 2
colormap([0.5 0.25 0 ; 0 0.8 1]);
elseif max(C(:)) >= 2 && max(C(:)) < 3
colormap([0.5 0.25 0 ; 0 0.8 1 ; 0 0.5 0.65]);
elseif max(C(:)) >= 3
colormap([0.5 0.25 0 ; 0 0.8 1 ; 0 0.5 0.65 ; 0 0.2 0.3]);
end
The result is that when the water level is below threshold 1 it is a light blue, between the two thresholds it turns darker, and above threshold 2 it turns darker yet.
My problem is that when I draw the legend
legend('ground','water');
... I only get one color representing the water, and it changes according to the max depth. How do I make a static legend showing all four categories with a color example:
(brown) Ground
(light blue) Water level beneath threshold 1
(standard blue) Water level between thresholds
(dark blue) Water level above threshold 2
The only solution I can think of is making 3 neat little patches somewhere by the axis (where it won't be noticed) in the right blue colors and then making the legend point at them and not the water surface. But that would be a real crappy solution...
You can display a colorbar():
C = [1 2 3 4];
if max(C(:)) < 2
colormap([0.5 0.25 0 ; 0 0.8 1]);
elseif max(C(:)) >= 2 && max(C(:)) < 3
colormap([0.5 0.25 0 ; 0 0.8 1 ; 0 0.5 0.65]);
elseif max(C(:)) >= 3
colormap([0.5 0.25 0 ; 0 0.8 1 ; 0 0.5 0.65 ; 0 0.2 0.3]);
end
% whatever to make your plot
imagesc(C);
% display a colorbar
cb_ax = colorbar;
% label it appropriately
set(cb_ax, 'YTick', [1:4]*3/4+5/8, 'YTickLabels', {'A', 'B', 'C', 'D'});