detecting finger valleys with Matlab [closed] - matlab

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a binary image of the hand like that:
I have to write a Matlab function that detects the valley between two fingers.
The parameters are the binary image and the coordinates of the two finger's tips.
I'm new in image processing and I don't know how to start.

I suggest to isolate the black area between the two input points, and then find the highest point in this connected component.
You can try the following approach (you may need to tweak some of the parameters, but it should be a good start).
I = rgb2gray(imread('<your path>'));
%input parameters - points which represents two finger tips.
x1 = 408; y1 = 441;
x2 = 454; y2 = 373;
%binarize image
I = im2bw(I);
%noise reduction - close holes
I2 = imclose(I,strel('disk',10));
%draw a line between p1 and p2
ind = drawline([y1 x1],[y2 x2],size(I));
lineMat = zeros(size(I));
lineMat(ind) = 1;
%adds the line to the image
I2 = I2 | lineMat;
%finds a point in the middle of the line
[lineY, lineX] = ind2sub(size(I),ind);
midX = lineX(ceil(length(ind)/2));
midY = lineY(ceil(length(ind)/2));
%finds a point which resides in the connected component which is between
%the line and the two finger.
xSeed = midX;
ySeed = midY -5;
%perform imfill operation, starting from (xSeed,ySeed),
%in order to find the conected component in which the point (xSeed,ySeed)
%resides.
diffMat = imfill(I2,[ySeed xSeed])~=I2;
%finding the highest point in this connected component
[Y, X] = ind2sub(size(diffMat),find(diffMat));
minInd = find(Y==min(Y),1,'first');
yValley = Y(minInd);
xValley = X(minInd);
%presents result
imshow(I);hold on;
plot(x1,y1,'r.','MarkerSize',20);
plot(x2,y2,'r.','MarkerSize',20);
plot(xValley,yValley,'b.','MarkerSize',20);
*draw line function is taken from drawline webpage.
Final result (input points in red, output point in blue).

It's just the algorithm, but all these function certainly exist in MatLab:
Compute the convex hull
Compute the difference: Convex Hull minus the original shape. Then you have all the valleys you are looking for, plus some small patterns.
Connected components labeling.
Delete the small components. Then you have all the valleys between the fingers.
Then you can select the one you want using the fingertip coordinates.

Related

If two rectangles intersection is zero in matlab [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Knowing center of the two rectangles and their angle by x axis (horizontal axis), how can one recognize if their intersection is zero or not in Matlab? Any answers containing this information is highly appreciated. Width and length of rectangles are also known
This is a programming problem if you want to solve it numerically. For exact solutions, you could use geometrical equations.
The first problem: defining a rectangle's corners from its width, height and centre:
C1 = [0, 0]; % Centre of rectangle 1 (x,y)
C2 = [1, 1]; % Centre of rectangle 2 (x,y)
W1 = 5; W2 = 3; % Widths of rectangles 1 and 2
H1 = 2; H2 = 3; % Heights of rectangles 1 and 2
% Define the corner points of the rectangles using the above
R1 = [C1(1) + [W1; W1; -W1; -W1]/2, C1(2) + [H1; -H1; -H1; H1]/2];
R2 = [C2(1) + [W2; W2; -W2; -W2]/2, C2(2) + [H2; -H2; -H2; H2]/2];
Next problem is to create many points which represent the edges of the rectangles. You could instead generate many points within the rectangles if you wanted to look at intersecting areas.
n = 1000; % Define some number of points to use
% Use interp1 to interpolate around the rectangles
R1points = interp1(1:5, [R1; R1(1,:)], linspace(1,5,n));
R2points = interp1(1:5, [R2; R2(1,:)], linspace(1,5,n));
Then rotate the rectangles:
a1 = deg2rad(0); a2 = deg2rad(30); % angles of rotation for rectangle 1 and 2 respectively
R1rotated(:,1) = (R1points(:,1)-C1(1))*cos(a1) - (R1points(:,2)-C1(2))*sin(a1) + C1(1);
R1rotated(:,2) = (R1points(:,1)-C1(1))*sin(a1) + (R1points(:,2)-C1(2))*cos(a1) + C1(2);
R2rotated(:,1) = (R2points(:,1)-C2(1))*cos(a2) - (R2points(:,2)-C2(2))*sin(a2) + C2(1);
R2rotated(:,2) = (R2points(:,1)-C2(1))*sin(a2) + (R2points(:,2)-C2(2))*cos(a2) + C2(2);
Finally, check intersection with inpolygon:
in1 = inpolygon(R1rotated(:,1), R1rotated(:,2), R2rotated(:,1), R2rotated(:,2));
in2 = inpolygon(R2rotated(:,1), R2rotated(:,2), R1rotated(:,1), R1rotated(:,2));
If nnz(in1)>0 or nnz(in2)>0 then you have an intersection! Visualise it using scatter:
hold on
scatter(R2rotated(:,1), R2rotated(:,2), '.b')
scatter(R2rotated(in2,1), R2rotated(in2,2), 'xc')
scatter(R1rotated(:,1), R1rotated(:,2), '.r')
scatter(R1rotated(in1,1), R1rotated(in1,2), 'xg')
Result:

Detecting almost surrounded background areas [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm doing image processing on tribological samples. I'm segmenting the wear track from the images, but have a recurring problem:
Setting the threshold too low leads to a complete failure. Setting it too high (as in the image) leads to multiple areas that are almost but not quite enveloped by the label. They mess up the distance transform I'm using to estimate track width, and should be detected and merged to the label.
I have used morphological operations to improve the quality of the label, but do not wish to make the structuring elements bigger due to some side effects in the rest of the image. The curvature of the label prevents me from using convex hulls. The bulk of the label prevents me from using the solidity of the label as an indicator. The unwanted interior objects are not enveloped completely by the label, so they can not be detected via the Euler characteristic etc.
Is there any good way to detect background objects that are 'almost completely' surrounded by foreground objects?
I used watershed to divide the background into separate regions and then bwboundaries to detect how much of a region's boundary is shared with the foreground object:
% generate example image
bw = im2double(rgb2gray(imread('example.jpg'))) == 1;
% dilate binary object to overlap watershed boundaries
bwDil = imdilate(bw,ones(5));
% get watershed labels
D = bwdist(bw);
D = -D;
D(bw) = -Inf;
L = watershed(D);
% get binary regions and remove fg object
R = (L > 0);
R(bw) = 0;
% get boundaries of all regions
BR = bwboundaries(R);
% set boundary ratio - if a regio's shares more boundary with fg object
% than this threshold it considered surrounded
boundaryRatio = zeros(numel(BR),1);
ratioThresh = 0.6;
mask = false(size(bw));
% go through region boundaries and add them to mask if above tresh
for ii = 1:numel(BR)
ind = sub2ind(size(bw),BR{ii}(:,1),BR{ii}(:,2));
boundaryRatio(ii) = nnz(bwDil(ind))/numel(ind);
if boundaryRatio(ii) > ratioThresh
mask(ind) = 1;
end
end
% fill mask
mask = imfill(mask,4,'holes');
% plot
subplot(121);
imshow(bw);
title('fg')
rgb = double(cat(3,mask,bw,bw));
subplot(122);
imshow(rgb);
title('fg with surrounded bg')

How to get pixel location of object in image [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Suppose I have a binary image shown in below. I want to get the location(pixel value in X,Y coordinates) of all rectangular shapes and also circular shapes. How to detect how many rectangular and circular shapes are present there. I want to get the solution in Matlab. The rectangle and circle may be in different size. The small circles are noise here. Thanks in advance.
You need to:
find connected components (bwconncomp)
find some statistic for each connected component (regionprops)
discard connected components that are too small, defining a threshold on the area
find if the connected component is a rectangle or a circle / ellipse. You can use the circularity, defined as 4*pi*Area / (Perimeter^2). Perfect circles will have value 1, squares 0.785, and so on. So you can define a threshold on circularity to determine if a shape is a circle/ellipse or not.
Here the result, with smaller blobs removed, and circles/ellipses and rectangles in different colors:
Code:
% Read image
img = imread('path_to_image');
% Convert to grayscale
img = rgb2gray(img);
% Remove JPEG artifacts
bw = img > 20;
% Prepare output image
output = zeros(size(bw));
% Compute connected components, and their statistics
cc = bwconncomp(bw);
props = regionprops(cc, 'Area', 'Perimeter');
% Will contain x,y coordinates for rectanles and circles
coord_rect = {};
coord_circ = {};
% Define thresholds on size and circularity
th_size = 200;
th_circ = 0.8;
% For each connected component
for i = 1 : cc.NumObjects
% Is big enough?
if(props(i).Area < th_size)
continue;
end
% Rectangle or Circle?
circularity = 4 * pi * props(i).Area / (props(i).Perimeter ^ 2);
[y,x] = ind2sub(cc.ImageSize, cc.PixelIdxList{i});
if(circularity > th_circ)
% Circle
output(cc.PixelIdxList{i}) = 1;
coord_circ{end+1} = [x, y];
else
% Rectangle
output(cc.PixelIdxList{i}) = 2;
coord_rect{end+1} = [x, y];
end
end
% Show results
imshow(bw);
figure();
imagesc(output);

Count black pixels within a circle [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have one vector of radii and second vector of hundreds of [X,Y] coordinates. For each possible coordinate-radius pair I have count all black pixels within a circle (whose center is placed in the coordinate) on an input binary image.
What is the fastest way to do it? My only idea is to iterate through every pixel of an image, check the circle equation and then the pixel color but it doesn't seem much optimized for several hundred such operations.
Matlab is great for working with images thanks to the matrix syntax. It does also work with indices so most time you can avoid "iterating through pixels" (although sometimes you'll still have to).
Instead of checking all the pixels within each circle, and having to detect how many pixels were counted twice, another approach is to create a mask, the same size of you image. Blank this mask for each of your circles (so overlapping pixels are only 'blanked' once), then apply the mask on your original picture and count the remaining illuminated pixels.
For an example, I have to take some sample data, the image:
load trees
BW = im2bw(X,map,0.4);
imshow(BW)
And 20 random point/circle coordinates (you can change the number of points and the min/max radii easily):
%// still building sample data
s = size(BW) ;
npt = 20 ; Rmin=5 ; Rmax=20 ; %// problem constants
x = randi([1 s(2)] ,npt,1); %// random X coordinates
y = randi([1 s(1)] ,npt,1); %// Y
r = randi([Rmin Rmax],npt,1); %// radius size between 5 to 20 pixels.
Then we build your custom mask :
%// create empty mask with enough overlap for the circles on the border of the image
mask = false( s+2*Rmax ) ;
%// prepare grid for a sub-mask of pixels, as wide as the maximum circle
xmask = -Rmax:Rmax ;
[xg,yg] = ndgrid(xmask,xmask) ;
rg = sqrt( (xg.^2+yg.^2) ) ; %// radius of each pixel in the subgrid
for ip=1:npt
mrow = xmask+Rmax+y(ip) ; %// calc coordinates of subgrid on original mask
mcol = xmask+Rmax+x(ip) ; %// calc coordinates of subgrid on original mask
cmask = rg <= r(ip) ; %// calculate submask for this radius
mask(mrow,mcol) = mask(mrow,mcol) | cmask ; %// apply the sub-mask at the x,y coordinates
end
%// crop back the mask to image original size (=remove border overlap)
mask = mask(Rmax+1:end-Rmax,Rmax+1:end-Rmax) ;
imshow(mask)
Then you just apply the mask and count :
%% // Now apply on original image
BWm = ~BW & mask ; %// note the ~ (not) operator because you want the "black" pixels
nb_black_pixels = sum(sum(BWm)) ;
imshow(BWm)
nb_black_pixels =
5283
Here is one implementation:
Advantages:
No loops, meshgrid/ndgrid. Instead used faster bsxfun and pdist2
Dots are counted only once, even when the circles overlap.
Variable radius used (radius of all circle is not same)
Code:
%// creating a binary image with little black dots
A = randi(600,256);
imbw = A ~= 1;
%// Your binary image with black dots
imshow(imbw);
%// getting the index of black dots
[dotY, dotX] = find(~imbw);
nCoords = 10; %// required number of circles
%// generating its random coordinates as it is unknown here
Coords = randi(size(A,1),nCoords,2);
%// calculating the distance from each coordinate with every black dots
out = pdist2(Coords,[dotX, dotY]).'; %//'
%// Getting only the black dots within the radius
%// using 'any' avoids calculating same dot twice
radius = randi([10,25],1,size(Coords,1));
pixelMask = any(bsxfun(#lt, out, radius),2);
nPixels = sum(pixelMask);
%// visualizing the results by plotting
hold on
scatter(dotX(pixelMask),dotY(pixelMask));
viscircles([Coords(:,1),Coords(:,2)],radius.'); %//'
hold off
Output:
>> nPixels
nPixels =
19

coloring specific point according to a given parameter [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am new to matlab coding and I know it's simple that's why I'm trying to plot 2D datas read from a file,but I'm stuck,with my following code I'm reading the x y coordinates and trying to plot specific point with specific indexing according to given criteria ( which is p in my case I won't go too much into details), all I want to know is how can I modify the code so that I can give the correct index to the point that I want to color(i.e when the condition is satisfied plot this specific points with blue or watever),here is my code :
M=load('data1.XYZ');
x=M(:,1); %all x coordinates
y=M(:,2); %all y coordinates
xA=M(1:400,1); % x of particles A
yA=M(1:400,2); % y of particles A
xB=M(401:800,1); % x of particles B
yB=M(401:800,2); % y of particles B
Pos1=[x y]; % read in the x y coordinates
[num1,junk1] = size(Pos1);
PosA=[xA yA]; % read in the x y A coordinates
PosB=[xB yB]; % read in the x y B coordinates
[numA,junkA] = size(PosA);
[numB,junkB] = size(PosB); %no of all B particles
fprintf('Determining Distances between particles...\n');
r = zeros(numA,1);
psil_avg=0.0+0.0i;
psir_avg=0.0+0.0i;
for m=1:numA
for n=1:numA
cnt_l=0;
psi_l=0.0+0.0i;
if(m~=n)
r(m,n)=norm(PosA(m,:)-PosA(n,:));
if(r(m,n)< 1.44)
v1=PosA(m,:)-PosA(n,:);
u=[0 1];
dot=v1(:,1).*u(:,1)+v1(:,2).*u(:,2);
N=norm(v1);
cosinus=dot/N;
theta=acos(cosinus);
cnt_l=cnt_l+1;
psi_l=psi_l+(cos(theta)+6.0i*sin(theta));
psil_avg=psi_l/cnt_l;
for k=1:numA
cnt_r=0;
psi_r=0.0+0.0i;
if(m~k)
r(m,k)=norm(PosA(m,:)-PosA(k,:));
if(r(m,k)< 1.44)
v2=PosA(m,:)-PosA(k,:);
u2=[0 1];
dot2=v2(:,1).*u2(:,1)+v2(:,2).*u2(:,2);
N2=norm(v2);
cosinus2=dot2/N2;
theta2=acos(cosinus);
cnt_r=cnt_r+1;
psi_r=psi_r+(cos(theta2)+6.0i*sin(theta2));
psir_avg=psi_r/cnt_r;
p=sqrt(psi_r*psi_l);
if p > 0.94
% fprintf('bond order parameter is %f\n',p);
plot(xA(n),yA(n),'ro','Markersize',6);
hold on;
else
plot(xA(n),yA(n),'go','Markersize',8);
end
end
end
end
end
end
end
end
if anyone can help I'd be thankful
Use scatter and the following properties:
'MarkerEdgeColor' — Marker edge color
[0 0 1] (blue) (default) | 'auto' | 'none' | three-element RGB vector | string
'MarkerFaceColor' — Marker face color
'none' (default) | 'auto' | three-element RGB vector | string
Your code is a bit hard to read so I will adress this quiestion in general.
If you have groups of coordinates you would like to plot with different colors say X1,Y1 and X2,Y2 you may do the following
figure
plot(X1,Y1,'r*')
hold on
plot(X2,Y2,'b*')
hold off
This will color the first group in red with a dot and the second with blue and a dot.
The hold on, hold off is made to plot more then one plot on a single axis without clearing the previous one.
As suggested in the comments - you should probably try to avoid looping in matlab.
I could not understand your question clearly. Do you mean like this ? For example if I have two plots
x = linspace(-2*pi,2*pi);
y1 = sin(x);
y2 = cos(x);
figure
plot(x,y1,x,y2)
Do you want different colours say red for 10,blue for 20, green for 30 degrees for both curves ? Is this what you want ? Please specify properly.