Finding points in array that is in the specified rectangle( matlab) - matlab

I have a matrix that is consists of some points of image.look at below
Cout=
[215,59;165,126;215,72;236,65;258,60;296,71;296,84;246,77;240,120;228,120;225,74;176,58;178,72];
Now I want to find points in rectangle below [x,y,width,height]
rec=[105,210,31,31]
How should I code it in Matlab?
Thanks.

Use inpolygon.[https://www.mathworks.com/help/matlab/ref/inpolygon.html]
HOW IT WORKS:
in = inpolygon(xq,yq,xv,yv) returns in indicating if the query points specified by xq and yq are inside or on the edge of the polygon area defined by xv and yv.
xq: x-coordinates of query points, specified as a scalar, vector, matrix, or multidimensional array(The size of xq must match the size of yq).
yq: y-coordinates of query points, specified as a scalar, vector, matrix, or multidimensional array.
xv: x-coordinates of polygon vertices, specified as a vector(The size of xv must match the size of yv).
yv: y-coordinates of polygon vertices, specified as a vector.
in: Indicator for the points inside or on the edge of the polygon area, returned as a logical array. in is the same size as xq and yq.
% points of image you're searching
% (x,y) are not the coordinates of matrices in MATLAB! And images are
% matrices. The coordinates of matrices are (row, column) which is NOT (x,y) - it's (y,x).
yq=Cout(:,1)
xq=Cout(:,2)
xv=[rec(1);rec(1);rec(1)+rec(3);rec(1)+rec(3);rec(1)];
yv=[rec(2);rec(2)+rec(4);rec(2)+rec(4);rec(2);rec(2)];
in = inpolygon(xq,yq,xv,yv)
I find 2 points by this way.

here is what you need (I think):
Cout= [235,65;296,71;296,84;240,120;229,119;224,74;165,126];
Rec=[105,210,31,31];
% set the range of the rectangle in x and y
xr=[Rec(2) (Rec(2)+Rec(4))];
yr=[Rec(1) (Rec(1)+Rec(3))];
% draw the rectangle for ref
rectangle('Position',Rec); hold on
% the next line is what you asked for, checking if points fall in the
% rectangle I chose here limits with < and >, but you may want <= and >= ...
id = Cout(:,1)<xr(end) & Cout(:,1)>xr(1) & Cout(:,2)<yr(end) & Cout(:,2)>yr(1);
% let's check:
plot(Cout(:,2),Cout(:,1),'x',Cout(id,2),Cout(id,1),'ro')

Related

Find closest point of labelled area to a point in an image with Matlab

I'm trying to find the closes point to an area in an image with Matlab:
consider this example code:
myimg = rgb2gray(imread('tissue.png')); %load grayscale example image of cells
BW=bwareaopen(myimg<150,10); %only look at dark pixels, remove small objects
BW=bwlabel(imfill(BW,'holes')) %fill holes of structures, label structures
figure;
imagesc(BW); %display image
I'd like to find the closest point of the closest structure to a point e.g. [0,0]. My approach so far is to get all centroids of all connected structures, then loop through all of them to find the closest one (inaccurate and inefficient).
If you just want to find a single closest point, you can use bwdist with a second output argument. This will give you a matrix which at each point contains the linear index of the closest non-zero point of the input image. You then just need to select the index corresponding to the point you are interested in. The input image to bwdist should be binary, so in your case you could try something like
% Make the image binary
binaryimage = BW > 0;
% Get the linear indices of the closest points
[~, idx] = bwdist(binaryimage);
% Find the linear index for point (3, 2)
x = 3;
y = 2;
pointindex = sub2ind(size(binaryimage), y, x);
% Find the index of the closet point from the segmentation
closestpointindex = idx(pointindex);
% Get coordinates of the closest point
[yc, xc] = ind2sub(size(binaryimage), closestpointindex);
This will give you the coordinates (xc, yc) and the matrix index (closestpointindex) of the pixel with a non-zero value in the binary image which is closest to the point (x,y), where x and y are Matlab indices, remembering that Matlab indices start at 1 and rows are first, i.e. BW(y,x).

How to find all the pixels within some distance from a given pixel?

How can I efficiently find all pixels (u',v') within a distance x from a given pixel (u,v). Specifically all (u',v') such that sqrt((u-u')^2 +(v-v')^2) <= x
To find all pixels at distance x you can use this indexing trick (for Manhattan distance)
u=10;v=10;
x=3.4;
pixels=img([floor(u-x) ceil(u+x)],[floor(v-x) ceil(v+x)]);
However, note that this will add any pixel that is within the distance, even if its just a piece of the pixel! E.g. (6,6) is inside!
For Euclidean distance, you need to define a circle around the point
[xi,yi]=meshgrid(1:size(img,1),1:size(img,2));
mask=sqrt((xi-u).^2+(yi-v).^2)<x; % or ceil(x)
pixel_values=img(mask);
[pixel_indices_u pixel_indices_v]=find(mask);
u = rand(1e2,1); % Create a 100 random points in the unit square
v = rand(1e2,1); % Create a 100 random points in the unit square
a = 0.3; % Choosen pixel
b = 0.4;
x = 0.1; % radius from the choosen pixel
idx = (sqrt((u-a).^2 +(v-b).^2) <= x); % Create a logical index array
locs = [u(idx) v(idx)]; % Index the locations
This is basically exactly what you describe in the question, with the points being labelled as (u,v) and the "destination point" so to speak labelled with (a,b) as a prime (') denotes the complex conjugate transpose in MATLAB.
Read more on logical indexing in this very insightful answer by Luis Mendo

How to create a 2D image by rotating 1D vector of numbers around its center element?

I have 1D vector of numbers which represents a center cut of a circular symmetric object. The vector itself is symmetric around its center element. I want to create in MATLAB a 2D image of the original object by rotating the 1D vector around its center element.
I tried the following code (with a dummy original vector of numbers) , but the center cut I get from the generated 2D image does not match the original 1D vector, as can be seen if you run the code.
I'll appreciate any help !!!
close all; clc
my1D_vector=[ zeros(1,20) ones(1,15) zeros(1,20)]; % original vector
len=length(my1D_vector);
img=zeros(len, len);
thetaVec=0:0.1:179.9; % angles through which to rotate the original vector
numRotations=length(thetaVec);
% the coordinates of the original vector and the generated 2D image:
x=(1:len)-(floor(len/2)+1);
y=x;
[X,Y]=meshgrid(x,y);
for ind_rotations=1:numRotations
theta=pi/180*thetaVec(ind_rotations);
t_theta=X.*cos(theta)+Y.*sin(theta);
cutContrib=interp1(x , my1D_vector , t_theta(:),'linear');
img=img+reshape(cutContrib,len,len);
end
img=img/numRotations;
figure('name','original vector');plot(x,my1D_vector,'b.-')
figure('name','generated 2D image'); imagesc(x,y,img); colormap(gray) ;
figure('name','comparison between the original vector and a center cut from the generated 2D image');
plot(x,my1D_vector,'b.-')
hold on
plot(x,img(find(x==0),:),'m.-')
legend('original 1D vector','a center cut from the generated 2D image')
I didn't follow your code but how about this:
V = [ zeros(1,20) ones(1,15) zeros(1,20)]; % Any symmetrical vector
n = floor(numel(V)/2);
r = [n:-1:0, 1:n]; % A vector of distance (measured in pixels) from the center of vector V to each element of V
% Now find the distance of each element of a square 2D matrix from it's centre. #(x,y)(sqrt(x.^2+y.^2)) is just the Euclidean distance function.
ri = bsxfun(#(x,y)(sqrt(x.^2+y.^2)),r,r');
% Now use those distance matrices to interpole V
img = interp1(r(1:n+1),V(1:n+1),ri);
% The corners will contain NaN because they are further than any point we had data for so we get rid of the NaNs
img(isnan(img)) = 0; % or instead of zero, whatever you want your background colour to be
So instead of interpolating on the angle, I interpolate on the radius. So r represents a vector of the distance from the centre of each of the elements of V, in 1D. ri then represents the distance from the centre in 2D and these are the values we want to interpolate to. I then only use half of r and V because they are symmetrical.
You might want to set all the NaNs to 0 afterwards because you can't interpolate the corners because their radius is larger than the radius of your furthest point in V.
Using your plotting code I get
and
The blue and magenta curves overlap exactly.
Explanation
Imagine that your vector, V, was only a 1-by-5 vector. Then this diagram shows what r and ri would be:
I didn't mark it on the diagram but r' would be the middle column. Now from the code we have
ri = bsxfun(#(x,y)(sqrt(x.^2+y.^2)),r,r');
and according to the diagram r = [2,1,0,1,2] so now for each pixel we have the euclidean distance from the centre so pixel (1,1) is going to be sqrt(r(1).^2+r(1).^2) which is sqrt(2.^2+2.^2) which is sqrt(8) as shown in the diagram.
Also you will notice that I have "greyed" out the corners pixels. These pixels are further from the centre than any point we have data for because the maximum radius (distance from the centre) of our data is 2 but sqrt(8) > sqrt(5) > 2 so you can't interpolate those data, you would have to extrapolate to get values for them. interp1 returns NaN for these points.
Why does the interpolation work? Think of the position of each pixel as referring to the centre of the pixel. Now in this diagram, the red circle is what happens when you rotate the outer elements (i.e. r==2) and the green is rotating the elements 1 further in (i.e. r==1). You'll see that the pixel that gets the distance of sqrt(2) (blue arrow) lies between these two radii when we rotate them and so we have to interpolate that distance between those two pixels.

Centroid calculation for a connected component in 3D volume using Matlab

I am trying to implement brain tumor segmentation on 3D brain MRI(.mha data type).
After preliminary segmentation, I am applying 26-neighbor connected component algorithm(using bwconncomp) to obtain the largest connected component by obtaining the component with the largest volume, following which I need to calculate the centroid of the resultant component.
I am not sure if my method of calculating the largest connected component and the centroid is correct, because the centroid obtained and its nearby voxels all have value 0.
Also I am having confusion with the representation of 3D voxel coordinates. For eg. if centroid=(x,y,z), does it correspond to x=row,y=column and z=2D slice?
Any help would be appreciated. Below is my code with the relevant part.
CC=bwconncomp(Ibin,26); %Input Black & White 3D data of size 240x240x155
Pixelid=regionprops(CC,'PixelIdxList');
[prow pcol]=size(Pixelid);
maxval=numel(Pixelid(1).PixelIdxList);
index=1;
for i=1:prow
number=numel([Pixelid(i).PixelIdxList]);
if (number>maxval) %calculating the component with max number of voxels
maxval=number;
index=i;
end
end
for i=1:prow
if i~=index
Ibin(Pixelid(i).PixelIdxList)=0;
end
end
CC1=bwconncomp(Ibin,26);
Cent=regionprops(CC1,'Centroid');
I changed your code to the following:
CC=bwconncomp(Ibin,26);
PixelIdxList = CC.PixelIdxList;
maxval = numel(PixelIdxList{1});
index = 1;
for ii = 1:length(PixelIdxList)
number = numel(PixelIdxList{ii});
if number > maxval
maxval = number;
index = ii;
end
end
[y,x,z] = ind2sub(size(Ibin),PixelIdxList{index})
centroid = [mean(x), mean(y), mean(z)];
bwconncomp already gives you a PixelIdxList so you don't have to use regionprops. The PixelIdxList lists pixels by their linear indices, so you have to convert them into subscripts to get x, y, and z coordinates. The first dimension in MATLAB matrix represents y coordinates, and second dimension represents x, while the third dimension represents z. Centroid is calculated by taking the mean x, y, and z coordinates of all the pixels contained in the object.

extracting matrix values from another matrix

I have a problem like that;
points (size = 65,2) is a variable that has pixel coordinates of an image. In the first column, there are x coordinates, and in the second y coordinates and I want to take the magnitude values of a matrix (size = 256,256,6) from those pixel coordinates of only one channel eg. 3 (three).
I couldn't succeed that.
intensities = images(points(:,2), points(:,1), 3);
makes a matrix 65x65.
Thanks
Jimenez
You can convert your x,y indices to linear indices to get values you want from your image:
% some sample data
list = round(256*rand(65,2));
im = rand(256,256);
% calculate linear indices
ind = sub2ind([256,256],list(:,1),list(:,2));
intensities = im(ind);
This results in an intensities matrix that is 65x1 where each element corresponds to the x,y pair from your list.