I have the follow code in matlab which is supposed to draw a polygon on a image (has to be a 2d image, be just a patch).
numCorners=8;
dotPos=[];
for rr=1:numCorners
dotPos(end+1)=(cos(rr/numCorners*2*pi))*100;
dotPos(end+1)=(sin(rr/numCorners*2*pi))*100;
end
BaseIm=zeros(1000,1000);
dotpos=[500,500];
imageMatrix =drawpolygon(BaseIm, dotPos, 1); or how else do draw a white polygon here?
imshow(imageMatrix);
This doesn't work as drawpolygon does not appear to exist in this way any idea how to do this?
Note that the resulting data must be an image of equal size of baseIM and must be an array of doubles (ints can be converted) as this is test data for another algorithm.
I have since found the inpolygon(xi,yi,xv,yv); function which I could combine with a for loop if I knew how to properly call it.
If you just need to plot two polygons, you can use the fill function.
t=0:2*pi;
x=cos(t)*2;
y=sin(t)*2
fill(x,y,'r')
hold on
fill(x/2,y/2,'g')
As an alternative, you can use the patch function:
figure
t=0:2*pi;
x=cos(t)*2;
y=sin(t)*2
patch(x,y,'c')
hold on
patch(x/2,y/2,'k')
Edit
The fill and patch functions allow to add polygons also over an actual image too.
% Load an image on the axes
imshow('Jupiter_New_Horizons.jpg')
hold on
% Get the axis limits (just to center the polygons
x_lim=get(gca,'xlim')
y_lim=get(gca,'ylim')
% Create the polygon's coords
t=0:2*pi;
x=cos(t)*50+x_lim(2)/2;
y=sin(t)*50+y_lim(2)/2
% Add the two polygons to the image
f1_h=fill(x,y,'r')
hold on
f1_h=fill(x/2,y/2,'g')
Hope this helps.
Related
I am currently doing some seismic modelling and processing in MATLAB, and would like to come up with an easy way of muting parts of various datasets. If I plot the frequency-wavenumber spectrum of some of my data, for instance, I obtain the following result:
Now, say that I want to mute some of the data present here. I could of course attempt to run through the entire matrix represented here and specify a threshold value where everything above said value should be set equal to zero, but this will be very difficult and time-consuming when I later will work with more complicated fk-spectra. I recently learned that MATLAB has an inbuilt function called impoly which allows me to interactively draw a polygon in plots. So say I, for instance, draw the following polygon in my plot with the impoly-function:
Is there anything I can do now to set all points within this polygon equal to zero? After defining the polygon as illustrated above I haven't found out how to proceed in order to mute the information contained in the polygon, so if anybody can give me some help here, then i would greatly appreciate it!
Yes, you can use the createMask function that's part of the impoly interface once you delineate the polygon in your figure. Once you use create this mask, you can use the mask to index into your data and set the right regions to zero.
Here's a quick example using the pout.tif image in MATLAB:
im = imread('pout.tif');
figure; imshow(im);
h = impoly;
I get this figure and I draw a polygon inside this image:
Now, use the createMask function with the handle to the impoly call to create a binary mask that encapsulates this polygon:
mask = createMask(h);
I get this mask:
imshow(mask);
You can then use this mask to index into your data and set the right regions to 0. First make a copy of the original data then set the data accordingly.
im_zero = im;
im_zero(mask) = 0;
I now get this:
imshow(im_zero);
Note that this only applies to single channel (2D) data. If you want to apply this to multi-channel (3D) data, then perhaps a multiplication channel-wise with the opposite of the mask may be prudent.
Something like this:
im_zero = bsxfun(#times, im, cast(~mask, class(im)));
The above code takes the opposite of the polygon mask, converts it into the same class as the original input im, then performs an element-wise multiplication of this mask with each channel of the input separately. The result will zero each spatial location that's defined in the mask over all channels.
On a shape from a logical image, I am trying to extract the field of view from any point inside the shape on matlab :
I tried something involving to test each line going through the point but it is really really long.(I hope to do it for each points of the shape or at least each point of it's contour wich is quite a few times)
I think a faster method would be working iteratively by the expansion of a disk from the considered point but I am not sure how to do it.
How can I find this field of view in an efficient way?
Any ideas or solution would be appreciated, thanks.
Here is a possible approach (the principle behind the function I wrote, available on Matlab Central):
I created this test image and an arbitrary point of view:
testscene=zeros(500);
testscene(80:120,80:120)=1;
testscene(200:250,400:450)=1;
testscene(380:450,200:270)=1;
viewpoint=[250, 300];
imsize=size(testscene); % checks the size of the image
It looks like this (the circle marks the view point I chose):
The next line computes the longest distance to the edge of the image from the viewpoint:
maxdist=max([norm(viewpoint), norm(viewpoint-[1 imsize(2)]), norm(viewpoint-[imsize(1) 1]), norm(viewpoint-imsize)]);
angles=1:360; % use smaller increment to increase resolution
Then generate a set of points uniformly distributed around the viewpoint.:
endpoints=bsxfun(#plus, maxdist*[cosd(angles)' sind(angles)'], viewpoint);
for k=1:numel(angles)
[CX,CY,C] = improfile(testscene,[viewpoint(1), endpoints(k,1)],[viewpoint(2), endpoints(k,2)]);
idx=find(C);
intersec(k,:)=[CX(idx(1)), CY(idx(1))];
end
What this does is drawing lines from the view point to each directions specified in the array angles and look for the position of the intersection with an obstacle or the edge of the image.
This should help visualizing the process:
Finally, let's use the built-in roipoly function to create a binary mask from a set of coordinates:
FieldofView = roipoly(testscene,intersec(:,1),intersec(:,2));
Here is how it looks like (obstacles in white, visible field in gray, viewpoint in red):
I am trying to map my image point by point to 3 dimensional space.
For example, if my original image has intensity of 100 at location X, I want to plot this point in 3D location Y with intensity of 100. I want to repeat this steps for every point/pixel, and get a final image. My biggest problem is that I want to do it point by point.
I appreciate any comments or advice. Thank you.
=======================
p.s.
As I was writing this question, I just came up with an idea. I know how to print 'whole' image into certain location/shape in 3D by using warp() function. Instead of using my whole image as an argument to warp function, if I give one point intensity value and one 3D point as arguments for warp function, and repeat this steps for every image point, will I get a descent looking final image in 3D? If there is a better function to use, please let me know.
Sounds like you are looking for scatter3:
I = imread('cameraman.tif');
[x y]=meshgrid(1:size(I,1), 1:size(I,2));
scatter3(x(:),y(:),I(:),15,I(:),'filled');
axis tight; colormap gray
And this is what you get (after some changes to view point):
PS,
I used a single scatter3 command to plot all the points at once. You may (I have no idea why you would like to do so) do it one by one
figure;
for ii=1:numel(x)
scatter( x(ii), y(ii), I(ii), 15, I(ii), 'filled');
hold on; % need this!
end
axis tight; colormap gray;
I am interested in extracting the objects inside the region.
For example,
Fig1 showed the intensity profile of my laser profile. According to the laser intensity, I divide the profile into 2 region of interest (ROI1 and ROI2).
Fig2 showed the overlap of my exp result of positive responses and the laser intensity profile. The positive response data file is composed of x and y coordinates. As you can see the results are scattered over the laser profile image.
Here is what I want to do, I want to extract the spots within the ROI2 and discard all the rest as shown in Fig3. How can I do it? Specifically, how can I define a irregular shape ROI2 in matlab and extract the coordinates of positive response data.
Thanks for the help.
As eykanal says, you can use the impoly function to create any sort of ROI you want in your image. A general solution for extracting coordiantes is to create the ROI you want, and the use find to extract the coordinates and some set operation to remove unwanted points. Like this:
imshow(image)
h = impoly() ; %# draw ROI1
ROI1 = createMask(h); %# create binary mask of ROI1
h2 = impoly(); %# draw dummy_ROI consisting of ROI1+ROI2
dummy_ROI = createMask(h2); %# create binary mask
ROI2 = dummy_ROI-ROI1; %# create ROI2
p = find(ROI2); %# find all coordinates of ROI2
points = intersect(ind,p); %# find all points with linear index ind that are
%# part of ROI2
I think this problem is easier than you think, provided you always segment the image along (what appear to be) contour lines. You want to select all points which have a value greater than contour line 1 and less than contour line 2. I'm not sure how you specified the contour lines, but the selection command should simply be:
#% let laserData be the image data (it looks like it should
#% be 512x256, so I'll assume that)
highBound = mean(contour1points);
lowBound = mean(contour2points);
selectedData = laserData(laserData > lowBound & laserData < highBound);
If, as it appears, you're simply setting contours based on value, then the mean(contour1points) could be replaced by a user-defined value, using the function to get the value of the pixel under the cursor which I can't happen to recall right now. If you want to define a polygon, check out the impoly function.
I don't know what representation you use for your ROIs, but I would suggest some methods:
If your ROI is an ellipse and you know its equation just apply it to the results coordinates. Use the sign to decide if whether it is inside or not
If your ROI is a polygon of some kind you can use the function inpolygon
You could render the ROIs to black and white images and easily test hit/miss.
Please provide more details regarding the ROI representation.
I have an image and two points,
and I want to read the pixels between these two points,
and resample them into a small 1x40 array.
I'm using EMGU which is a C# wrapper for OpenCV.
thanks,
SW
What you are looking for is Bresenham's line algorithm. It will allow you to get the points in the pixel array that best approximate a straight line. The Wikipedia link also contains psuedo code to get you started.
Emgu CV includes method in the Image class for sampling color along a line called Sample.
Refer to the manual for the definition. Here's the link to Image.Sample in version 2.3.0.
You will still have to re-sample/interpolate the points in array returned from Sample to end up with a 40 element array. Since there are a number of ways to re-sample, I'll suggest you look to other questions for that.
Rotate and crop
I'd first try to do it like this:
calculate rotation matrix with (GetRotationMatrix2D)
warp the image so that this line is horisontal (WarpAffine)
calculate new positions of two of your points (you can use Transform)
get image rectangle of suitable width and 1 px high (GetRectSubPix)
Interpolation here and there may affect the results, but you have to interpolate anyway. You may consider cropping the image before rotation.
Iterate over the 8-connected pixels of the line
Otherwise you may use the line iterator to iterate over the pixels between two points. See documentation for InitLineIterator (Sorry, the link is to the Python version of OpenCV, I've never heard of EMGU). I suppose that in this case you iterate over pixels of a line which was not antialiased. But this should be much faster.
Interpolate manually
Finally, you may convert the image to an array, calculate which elements the line is passing through and subsample and interpolate manually.