Find coordinate on boundary of BW image - matlab

I need to find a specific point on an image in MATLAB, where the object I need to measure 'starts'. It's an image of a droplet laying on surface, and I would like to know how to find the x coordinate where the droplet starts.
I have a large dataset of these kind of images and the coordinates where the droplet starts is different for every image.
So my question is, is there a way to find the coordinates of this 'starting point' in MATLAB?

I managed to do it. This is probably not the best way, but it seems to work!
% Check X coordinate of start droplet
[B] = bwboundaries(FBW, 'noholes');
for k = 1:length(B)
boundary = B{k};
for l = 70:length(boundary)
dY(l) = (boundary(l,1) - boundary((l-15),1));
startDropletH = find([dY(:)] < -2, 1, "first")-5;
end
end
It first stores all the points on the border, then calculates and stores the dY over 15 X points, from which it looks up the first time dY<-2, which indicates the droplet is starting.

Related

Plotting a sequence of xy coordinates in Matlab. Can I make the colour get darker as the sequence progresses?

I have a set of xy coordinates in a matrix X = [x1,x2,... ; y1,y2,...]. The points come from finding the root of a function iteratively. I'd like to plot each coordinate on a Cartesian grid, but ideally have some way to distinguish the earlier coordinates from the later one. So for example, if I could plot each point, and have the colour get a bit darker with each point, then the viewer would be able to see how the points actually do converge. Is there a way to specify this somehow?
There should be so many ways to do this, as it is a simple task, BTW.
Example:
hold on
k = 0;
while (true)
k = k+1;
if k == 10; break; end % just to stop loop
r = k/10; % something linked to the found root
plot(k,k,'*','Color',[r,r,r]); % your plot
end
So basically, you link r to the found root or to something that shows the distance from the root.
This solution should give you idea, hopefully.

To detect irregular circles in MATLAB

I am new to MATLAB Image Processing. I am writing a code to detect some irregular circles, remove the remaining noise from the Image and find the center mean point of the irregular Black circles (ellipse). Here is the Image
This is the code I have written so far
m = imread('cbnimg.jpg');
imshow(m)
im = mean(m,3);
im = (im-min(im(:))) / (max(im(:))-min(im(:)));
figure;
imshow(im,[]);
impixelinfo
figure;
bin = im2bw(im);
imshow(bin);
figure;
bin = edge(bin);
SE = strel('disk',2);
cir =~imdilate(bin,SE);
imshow(cir);
Here is the result image of this code
[IMG]http://i61.tinypic.com/30n9egn.png[/IMG]
I want to detect only the black spots (Irregular Cicrcle) and remove the remaining noise from the picture as I want the Center Mean Point of these Black irregular Circles..
Can anyone suggest me some algorithms or techniques to get my center mean point?
Thank You
A very naïve approach: apply erosion twice and the dilation twice after a binarization:
m = imread('cbnimg.jpg');
imshow(m)
im = mean(m,3);
im = (im-min(im(:))) / (max(im(:))-min(im(:)));
bin = im2bw(im);
SE = strel('disk',10);
bin = ~imerode(~bin,SE);
bin = ~imerode(~bin,SE);
bin =~imdilate(~bin,SE);
bin =~imdilate(~bin,SE);
imshow(bin);
The shape of the circles is a bit changed, but the change in the center point should be really small. If you want something more ellaborated and robust, erode, label the elements in the image, divide them in two clusters depending on the mass (number of pixels) of each label (with k-means for instance) and then discard all the label correspoding to the cluster with lower masses.
However, for what you asked so far this should be enough.

Draw and estimate the lenght of a line in a image using matlab

I would like to draw a line between two edges on a grayscale image and estimate its length. Need to estimate the diameter of the femoral head. I have tried using houghlines and finally plot (see below) but can't get the code right. I am new to matlab which is probably why. Would be thankful for any hints!
for img = imread(sample);
figure,imshow(img)
hold on
p1 = [10,100];
p2 = [100,20];
plot([p1(2),p2(2)],[p1(1),p2(1)],'Color','r','LineWidth',2);
hold off;
pause;
end
I'm not really sure how you obtain the points. Suppose it's not trivial.
For similar problems my users always want to be able to mark the points manually (they don't trust computer vision a bit). The code the looks like this:
pos = ginput(2);
l = line(pos(:,1),pos(:,2),'Color','r','Marker','o'); % just for visualization
distance = norm(pos(1,:)-pos(2,:));
If you know the start and end points of the line
p1 = [ 10 100];
p2 = [100 20];
then the distance in pixels would simply follow from the Pythagorean theorem:
dist = sqrt( (p2-p1) * (p2-p1).' );
Then multiply this by however many millimeters a pixel represents to get the actual distance.
If you don't know the points, but draw them manually (perhaps aided by computer vision, but never fully reliant on it :), see bdecaf's answer.

Image processing and moments

In a project I'm currently working on I have to calculate the 5 moments of the contour of an image. Which I can then for example use to get the centroid. To do this I used matlab :
f = imread(Is);
%Edge detection with prewitt
contourImage = edge(f,'prewitt');
% Morphological operation to close the open spaces
se = strel('disk',2);
closecontourImage = imclose(contourImage,se);
imshow(closecontourImage);
%Find the x y positions of all the nonzero elements of the edge
[row,col] = find(closecontourImage);
% 3 moments
m10= 0;
m00= 0;
m01= 0;
mu00 =0;
% Calculate the 3 moments based on the given paper
for r=1:length(row)
for c=1:length(col)
m10 = m10 + ((row(r)^1)*(col(c)^0));
m00 = m00 + ((row(r)^0)*(col(c)^0));
m01 = m01 + ((row(r)^0)*(col(c)^1));
end
end
% Calculate centroid (zwaartepunt) based on the given formulas
x = m10/m00;
y= m01/m00;
Original image (in png, i use pgm in matlab):
The edge (which I assume is the contour):
The plot with the Image and the centroid
When I compare this to matlabs built in centroid calculation it is pretty close.
Though my problem is concerning the area calculation. I read that the 0th moment = area. though my m00 is not the same as the area. Which is logical because the 0th moment is a summation of all the white pixels ... which only represent the edge of the image, therefore this couldn't result in the area. My question is now , is there a difference in contour moments and moments on the entire image ? And is it possible to get the area based on the contour in this representation ?
In my assignment they explicitly say that the moments of the contour should be calculated and that the 1ste moment is equal to the centroid (which is also not the case in my algorithm). But what I read here is that the 1st order central moment = the centroid. So does this mean that the contour moments are the same as the central moments ? And a more general question, can i use this edge as a contour ?
I find these moments very confusing
There is a difference between moments of filled area or its contour. Think about the following case:
The contour is the exactly the same for both of these objects. Nevertheless, it is obvious that the center of weight in the right square is biased to the right, since it is "more full to the right".

Matlab - Propagate points orthogonally on to the edge of shape boundaries

I have a set of points which I want to propagate on to the edge of shape boundary defined by a binary image. The shape boundary is defined by a 1px wide white edge.
I have the coordinates of these points stored in a 2 row by n column matrix. The shape forms a concave boundary with no holes within itself made of around 2500 points. I have approximately 80 to 150 points that I wish to propagate on the shape boundary.
I want to cast a ray from each point from the set of points in an orthogonal direction and detect at which point it intersects the shape boundary at. The orthogonal direction has already been determined. For the required purposes it is calculated taking the normal of the contour calculated for point, using point-1 and point+1.
What would be the best method to do this?
Are there some sort of ray tracing algorithms that could be used?
Thank you very much in advance for any help!
EDIT: I have tried to make the question much clearer and added a image describing the problem. In the image the grey line represents the shape contour, the red dots the points
I want to propagate and the green line an imaginary orthongally cast ray.
alt text http://img504.imageshack.us/img504/3107/orth.png
ANOTHER EDIT: For clarification I have posted the code used to calculate the normals for each point. Where the xt and yt are vectors storing the coordinates for each point. After calculating the normal value it can be propagated by using the linspace function and the requested length of the orthogonal line.
%#derivaties of contour
dx=[xt(2)-xt(1) (xt(3:end)-xt(1:end-2))/2 xt(end)-xt(end-1)];
dy=[yt(2)-yt(1) (yt(3:end)-yt(1:end-2))/2 yt(end)-yt(end-1)];
%#normals of contourpoints
l=sqrt(dx.^2+dy.^2);
nx = -dy./l;
ny = dx./l;
normals = [nx,ny];
It depends on how many unit vectors you want to test against one shape. If you have one shape and many tests, the easiest thing to do is probably to convert your shape coordinates to polar coordinates which implicitly represent your solution already. This may not be a very effective solution however if you have different shapes and only a few tests for every shape.
Update based on the edited question:
If the rays can start from arbitrary points, not only from the origin, you have to test against all the points. This can be done easily by transforming your shape boundary such that your ray to test starts in the origin in either coordinate direction (positive x in my example code)
% vector of shape boundary points (assumed to be image coordinates, i.e. integers)
shapeBoundary = [xs, ys];
% define the start point and direction you want to test
startPoint = [xsp, ysp];
testVector = unit([xv, yv]);
% now transform the shape boundary
shapeBoundaryTrans(:,1) = shapeBoundary(:,1)-startPoint(1);
shapeBoundaryTrans(:,2) = shapeBoundary(:,2)-startPoint(2);
rotMatrix = [testVector(2), testVector(1); ...
testVector(-1), testVector(2)];
% somewhat strange transformation to keep it vectorized
shapeBoundaryTrans = shapeBoundaryTrans * rotMatrix';
% now the test is easy: find the points close to the positive x-axis
selector = (abs(shapeBoundaryTrans(:,2)) < 0.5) & (shapeBoundaryTrans(:,1) > 0);
shapeBoundaryTrans(:,2) = 1:size(shapeBoundaryTrans, 1)';
shapeBoundaryReduced = shapeBoundaryTrans(selector, :);
if (isempty(shapeBoundaryReduced))
[dummy, idx] = min(shapeBoundaryReduced(:, 1));
collIdx = shapeBoundaryReduced(idx, 2);
% you have a collision with point collIdx of your shapeBoundary
else
% no collision
end
This could be done in a nicer way probably, but you get the idea...
If I understand your problem correctly (project each point onto the closest point of the shape boundary), you can
use sub2ind to convert the "2 row by n column matrix" description to a BW image with white pixels, something like
myimage=zeros(imagesize);
myimage(imagesize, x_coords, y_coords) = 1
use imfill to fill the outside of the boundary
run [D,L] = bwdist(BW) on the resulting image, and just read the answers from L.
Should be fairly straightforward.