I am looking to plot the intersection of two surfaces(patches) lying the same plane in MATLAB.
As you can see in the above picture the green circle intersects four red rectangles.I want to plot out(or patch) only the four intersections.How do I proceed?
I tried to plot points on the circular patch which lies outside the intersection of one rectangle and circle using conditional statements.But MATLAB throws an error.Here is the code snippet.
[p,q] = size(points);
for s=1:1:q;
t = points(1,s);
if (points(1,s) >= Pa3(1,1)) && (points(1,s) <= Pa2(1,1)) && (points(2,s) >= Pa3(1,2)) && (points(2,s) <= Pa4(1,2))
points(1,s) = 0;points(2,s) = 0;
end
end
fill3(points(1,:), points(2,:), points(3,:), 'g');
The above code throws an error at if statement.Basically in the code "points" represent all the points in the green circle.Pa1,Pa2,Pa3,Pa4 represent the vertices of the left top corner rectangle with Pa1 being the left corner top vertex and Pa2,Pa3,Pa4 following in clockwise manner.
Thanks
Patches are defined by polygons, and what you are looking for is the intersection of two polygons which itself is a polygon.
If you have the Mapping Toolbox, you can use polybool to compute the intersection and other logical operations on polygons.
If not, have a look at the submission Polygon_Intersection on the Matlab File Exchange.
See also intersection and union of polygons.
Related
I would like to kindly ask you for the help with the definition of the line thickness. I have the binary curve. I need to find out a distance of each point of the curve skeleton to line edge in the direction of the normal. So, I firstly computed skeleton of the binary curve. Consequently, for each pixel of the skeleton I computed normal. This situation is depicted on the figure, showing the skeleton and a map of normal vectors from each pixel. In this point, I do not know how to compute the distance for each skeleton pixel to curve edge in the normal direction. Practically, I need to count number of the pixels (logical 1) from the skeleton pixels to the line edge in the normal direction. It means I need to obtain the vector, containing distance for each skeleton point. I would like to thank you in advance for your help.
Code for generating skeleton with normals:
clc;clear all;close all
i=rgb2gray(imread('Bin_Lines.bmp'));
BW=bwskel(logical(i));
% BW = image sceleton
Orientations = skeletonOrientation(BW,5); %5x5 box
Onormal = Orientations+90; %easier to view normals
Onr = sind(Onormal); %vv
Onc = cosd(Onormal); %uu
[r,c] = find(BW); %row/cols
idx = find(BW); %Linear indices into Onr/Onc
figure()
imshow(BW,[]);
%Plotting normals of binary skeleton
hold on
quiver(c,r,-Onc(idx),Onr(idx));
Here is the link where I store source codes and binary line image:
https://www.dropbox.com/sh/j84ep3k1604hsza/AABm92TUBX6yIp29Gc0v_PHHa?dl=0
You can use distance transform to compute the distance of each interior pixel to the boundary. Matlab has bwdist to do that for you.
Then you can extract the information for the skeleton pixels.
img = rgb2gray(imread('Bin_Lines.bmp'));
bw = bwskel(img > 128);
dst = bwdist(img <= 128); % need opposite contrast
distance_of_skel_pixels_to_boundary = dst(bw)
The distance dst looks like:
I am looking for a way to isolate the x and/or y coord of a circle within a circle, as shown in the image.
I need to isolate this so i can set a condition that when a ball enters a circle, i can change some qualities of the ball, i have been able to do this for the outer circle, which is centred at [0 0] using the code below,
while sqrt(XY(1)^2 + XY(2)^2) < 5
but cannot figure out how to do it for the interior circles.
Thanks
If you know the center and the radius of the inner circles you are able to calculate the X and Y coordinates of the circles then, you can use the inpolygon function to thest if a point is inside a circle (inpolygon returns 1 if a point is inside the polygon, 0 otherwise). In this case the polygon is constitued by the points of the circles.
In the following code a point moves across three circles (two of them placed inside the bigger one).
The inpolygon function is used to test if the point (the ball) is inside a circle and in change its colour according to the circle it is inside to.
% Define the radius and centre of three circles
r1=10;
r2=3
r3=4
c1=[0 0];
c2=[3 3];
c3=[-4 -4]
% Calculate the X and Y coord of the three circles
t=0:.01:2*pi;
x=cos(t)*r1
y=sin(t)*r1
x1=cos(t)*r2+c2(1)
y1=sin(t)*r2+c2(2)
x2=cos(t)*r3+c3(1)
y2=sin(t)*r3+c3(2)
% Plot the circles
plot(x,y,'r')
hold on
plot(x1,y1,'g')
plot(x2,y2,'b')
daspect([1 1 1])
% Define the ball trajectory
mx=-10:1:10;
my=-10:1:10;
for i=1:length(mx)
% Plot the ball: black if outside of all the circle
mh=plot(mx(i),my(i),'o','markerfacecolor','k','markeredgecolor','k')
% If the ballk is inside the first circle, make it red
if(inpolygon(mx(i),my(i),x,y))
mh.MarkerFaceColor='r';
mh.MarkerEdgeColor='r';
end
if(inpolygon(mx(i),my(i),x1,y1))
% If the ballk is inside the second circle, make it green
mh.MarkerFaceColor='g';
mh.MarkerEdgeColor='g';
end
if(inpolygon(mx(i),my(i),x2,y2))
% If the ballk is inside the third circle, make it blue
mh.MarkerFaceColor='b';
mh.MarkerEdgeColor='b';
end
pause(1)
end
Hope this helps.
Qapla'
l have generated a topology of a network with 200 nodes.than l want to draw a circle with black color around a choosen node(satisfying a certain condition IF (condition) ).
to simplify let the user introduce the the index of the node to circle with the black color.
here is my code of the generated topology.l need to add wich instructions to draw the circle around the choosen node ?
X=100;
Y=100;
N=200; %number of nodes
nodesX(1)=rand*X;
nodesY(1)=rand*Y;
for i=2:N
nodesX(i)=rand*X;
nodesY(i)=rand*Y;
d(i-1) =((nodesX(i)-nodesX(i-1)).^2+(nodesY(i)-nodesY(i-1)).^2).^0.5;
while (d(i-1)>200)
nodesX(i)=rand*X;
nodesY(i)=rand*Y;
d(i-1) =((nodesX(i)-nodesX(i-1)).^2+(nodesY(i)-nodesY(i-1)).^2).^0.5;
end
end
h_old=plot(nodesX,nodesY,'m*');
labels=[1:N]';
labels=num2str(labels);
text(nodesX,nodesY,labels);
xlabel('X (Meters)');
ylabel('Y (Meters)');
title(['Network Topology with',num2str(N),'nodes']);
hold on
for k=1:N;
for j=1:N;
if (k~=j)
d=((nodesX(k)-nodesX(j))^2+(nodesY(k)-nodesY(j))^2)^0.5;
end
if (k~=j);
if(d < 50);
line([nodesX(k),nodesX(j)],[nodesY(k),nodesY(j)]);
end
end
end;
end;
Split it into two tasks:
Task 1:
Define a simple function to draw a circle. A cheap and dirty way is to use polar expressions.
function [] = circle(center_x,center_y,r)
theta = 0:0.01:2*pi;
x = center_x + r*cos(theta);
y = center_y + r*sin(theta);
plot(x,y,'k','LineWidth',2)
Task 2:
Pass this function the NodeX and NodeY values of the indexed node as the point at which the circle is centered. You can set the radius of the circle as per your choice. Using r=1 and picking an arbitrary index, I got:
Just one caveat: Make sure your axis are square. Otherwise, a circle might look like an ellipse. If you want to draw a circle around non-square axis, then you can modify the code to generate an ellipse instead.
For exactly the same image
Opencv Code:
img = imread("testImg.png",0);
threshold(img, img_bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat tmp;
img_bwR.copyTo(tmp);
findContours(tmp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// Get the moment
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false );
}
// Display area (m00)
for( int i = 0; i < contours.size(); i++ )
{
cout<<mu[i].m00 <<endl;
// I also tried the code
//cout<<contourArea(contours.at(i))<<endl;
// But the result is the same
}
Matlab code:
Img = imread('testImg.png');
lvl = graythresh(Img);
bw = im2bw(Img,lvl);
stats = regionprops(bw,'Area');
for k = 1:length(stats)
Area = stats(k).Area; %m00
end
Any one has any thought on it? How to unify them? I think they use different methods to find contours.
I uploaded the test image at the link below so that someone who is interested in this can reproduce the procedure
It is a 100 by 100 small 8 bit grayscale image with only 0 and 255 pixel intensity. For simplicity, it only has one blob on it.
For OpenCV, the area of contour (image moment m00) is 609.5 (Very odd value)
For Matlab, the area of contour (image moment m00) is 763.
Thanks
Exist many different definitions of how contours should be extracted from binary image. For example it can be polygon that is the perimeter of white object in a binary image. If this definition was used by OpenCV, then areas of contours would be the same as areas of connected components found by Matlab. But this is not the case. Contour found by findContour() function is the polygon that connects centers of neighbor "edge pixels". Edge pixel is a white pixel that has black neighbor in N4 neighborhood.
Example: suppose you have an image whose size is 100x100 pixels. Every pixel above the diagonal is black. Every pixel below or on the diagonal is white (black triangle and white triangle). Exact separation polygon will have almost 200 vertexes at distance of 1 pixel: (0,0), (1,0), (1,1), (2,1), (2,2),.... (100,99), (100,100), (0,100). As you can see this definition is not very good from practical point of view. Polygon returned by OpenCV will have exactly 3 vertexes needed to define the triangle: (0,0), (99,99), (0,99). Its area is (99 x 99 / 2) pixels. It is not equal to number of white pixels. It is not even an integer. But this polygon is more practical than previous one.
Those are not the only possible definitions for polygon extraction. Many other definitions exist. Some of them (in my opinion) may be better than the one used by OpenCV. But this is the one that was implemented and used by a lot of people.
Currently there no effective workaround for your problem. If you want to get exactly same numbers from MATLAB and OpenCV you will have to draw the contours found by foundContours on some black image, and use function moments() on image. I know that upcoming OpenCV 3 have function that finds connected components but I didn't tried it myself.
I have skeletonize binary image and the junction information. I want to draw circle at junction points as center and want to find the point of intersection of circle and binary image.
I have written the following code:
BW = imread('circles.png');
imshow(BW);
BW2 = bwmorph(BW,'remove');
figure, imshow(BW2)
BW3 = bwmorph(BW,'skel',Inf);
figure, imshow(BW3)
BW3t = bwmorph(BW3,'thin');
figure, imshow(BW3t)
[rj, cj, re, ce] = findendsjunctions(BW3t, 1);
hold on
plot(cj(1),rj(1),'ob')
hold on
circle([cj(1),rj(1)],4,50,':r');
findendsjunctions.m and dependent file show.m can downloaded from here: http://www.csse.uwa.edu.au/~pk/research/matlabfns/LineSegments/findendsjunctions.m and here http://www.csse.uwa.edu.au/~pk/research/matlabfns/Misc/show.m respectively.
And circle.m can be downloaded from here: http://www.mathworks.co.uk/matlabcentral/fileexchange/2876-draw-a-circle/content/circle.m
I want to find whether circle intersect 2, 3 or 4 vessels around it (marked as star in an image). Even if circle transverse many times a single vessel but output should be one intersection point per vessel.
Please suggest how can I find the intersection of circle and binary vessels.
Thanks
I have found the point of intersection of circle and Binary image and the coordinates of 3 points (marked as star in an image provided with my question). I have change the function circle.m (mentioned in my question above ) to give output of all X and Y coordinates of circumference of the circle and then I have written the following matlab code:
[H, X, Y]=circle([cj(1),rj(1)],4,50,':r');
c = improfile(BW3t,X,Y)
x=1:length(c)
figure
plot(x, c,'r')
[maxtab, mintab]=peakdet(c, 1)
[pks,locs] = findpeaks(c)
pt1=[X(locs(1)) Y(locs(1))]
pt2=[X(locs(2)) Y(locs(2))]
pt3=[X(locs(3)) Y(locs(3))]
hold on
plot(pt1(1),pt1(2),'om','LineWidth',2)
hold on
plot(pt2(1),pt2(2),'og','LineWidth',2)
hold on
plot(pt3(1),pt3(2),'ob','LineWidth',2)
pt1, pt2 pt3 are three points where circle cuts the binary image