Issue with imdistline() function in MATLAB? - image

I am trying to measure the distance two points on an image and then use that distance as an input for some other function.
Here is my code:
figure, imshow(I);
h = imdistline(gca);
api = iptgetapi(h);
width = api.getDistance();
When I run it, I am able to drag and get the distance I want on the image, but the distance I get from using the getDistance is some default value it started with , when it opened and it does not change , even if I change it in the image. How can the variable width have the distance i measured before I press enter or any eye and close the image.
Eric

You should wait with the getDistance() function:
% create random image
I = rand(100);
figure, imshow(I);
h = imdistline(gca);
api = iptgetapi(h);
% wait for key pressed
pause('on');
pause;
% get line
width = api.getDistance();
disp(width);
Now the image appears, you can move your distance measure, then focus matlab console and press any key to get the result.

Related

How do I save just figure image without any graduation and numbers on x, y axis?

I used matlab code.
img = imread('cmap3.png')
map = jet(256)
ind = rgb2ind(img,map)
colormap(map)
cm = colormap('gray)
image(ind)
Through above code, I got the .
I want to save just the gray scale image without any graduations and numbers on x,y axis.
How do I remove them and save gray scale image?
If you use imwrite, you won't save the axes' labels.
For actual plots, there exists a different solutions, eg. described here: set the axis to start at the very left bottom corner so that there is no space left for descriptions: set(gca, 'Position',[0 0 1 1]). Than you can even use print to save the image/figure.

MATLAB crop image and make more blue not displaying change

In Matlab, I am trying to crop an image and be able to manipulate in some way (I adjusted contrast) and show change in formatting as its displayed beside the original image (by making it turn more and more blue).
The code runs successfully, but it seems to already have made the cropped image as blue as the for loop would take it.
How can I edit the code so that as the original is displayed beside the cropped, the cropped image is showing the change in formatting of turning more and more blue?
Here's what I have so far:
I = imread('peppers.png');
I2 = imcrop(I);
I3 = imadjust(I2,[.2 .3 0; .6 .7 1],[]);
subplot(1,2,1), subimage(I);
for i = 1:0.1:7
I3(:,:,3) = I3(:,:,3) + i;
subplot(1,2,2), subimage(I3)
end
To understand what is meant by showing an image to turn more and more blue upon display, please run:
img = imread('peppers.png');
for i = 1:0.1:7
figure(1)
img(:,:,3) = img(:,:,3) + i;
imshow(img)
end
If I understand what you want correctly, you want to display the original image on the left, and the bluer image on the right, and showing it progressively going blue as the loop is iterating. What I suggest you do is pause at each iteration in the loop to give you time to see the results. You can also put a title that shows what value i is at each iteration before the image changes. Also, make sure you add a drawnow command before you pause to flush the buffer so that you can visualize the results immediately. In other words, try this:
I = imread('peppers.png');
I2 = imcrop(I);
I3 = imadjust(I,[.2 .3 0; .6 .7 1],[]);
figure;
subplot(1,2,1);
subimage(I);
for i = 1:0.1:7
I3(:,:,3) = I3(:,:,3) + i;
subplot(1,2,2);
subimage(I3);
title(num2str(i)); %// Change - add title
drawnow; %// Change - flush buffer
pause(0.3); %// Change - add a pause
end
You should see the change in the blue channel for each value of i every 0.3 seconds. Change the value of 0.3 according to your tastes. BTW, the image is uint8, so adding floating point values to the blue channel will have no effect as these values will be truncated. Only integer values will show something appreciable.

visualizing Optical flow in matlab

I have an image with size 240*320 and I have the optical flow result with vertical and horizontal values. I need to visualize Optical flow by arrows on original image. I know that I have to use quiver function. Something like:
imshow(image)
hold on
quiver(vx,vy)
hold off
But what I get is a blue square instead of quivers.
An entirely blue square is probably caused by way too many arrows plotted close together.
For example, the following code will produce an easy-to-see (if not very meaningful) set of arrow:
figure
data = imread('peppers.png');
imshow(data)
s = size(data);
hold on
[x,y] = meshgrid(1:50:s(2),1:50:s(1));
px = cos(x);
py = sin(y);
quiver(x,y,px,py)
And this will produce an entirely blue plot:
figure
data = imread('peppers.png');
imshow(data)
s = size(data);
hold on
[x,y] = meshgrid(1:1:s(2),1:1:s(1)); % arrow spacing is too close!
px = cos(x);
py = sin(y);
quiver(x,y,px,py)

zooming in one subplot and then display it in another subplot

I have created a GUI which has 2 subplots.The first one display original image.
How can i do when i want to zoom in first subplot and then display it in second subplot? Thanks in advance
You can do that by copying the data from the first subplot to the second and setting the axis limits. Here's an example that doesn't use a GUI but should work the same way:
figure
% create two subplots
ax1 = subplot(2,1,1);
ax2 = subplot(2,1,2);
% display some data in the first subplot
axes(ax1);
imagesc(spiral(10));
% get the range of the axes in the first subplot
xLim1 = get(ax1, 'XLim');
yLim1 = get(ax1, 'YLim');
% Ask the user to zoom in. Instead of pressing
% enter, there could be a button to push in
% a GUI
reply = input('Zoom in and press enter');
% Get the new, zoomed in axes
zoomedXLim = get(ax1, 'XLim');
zoomedYLim = get(ax1, 'YLim');
% get the data from the first axis and display
% it in the second axis.
data = getimage(ax1);
axes(ax2)
imagesc(data)
% set the second axis to the zoomed range
set(ax2, 'XLim', zoomedXLim)
set(ax2, 'YLim', zoomedYLim)
title('zoomed image')
% return the first axis to its original range.
set(ax1, 'XLim', xLim1)
set(ax1, 'YLim', yLim1)
axes(ax1)
title('original image')
The resulting figure will look something like this:

How can I draw a circle on an image in MATLAB?

I have an image in MATLAB:
im = rgb2gray(imread('some_image.jpg');
% normalize the image to be between 0 and 1
im = im/max(max(im));
And I've done some processing that resulted in a number of points that I want to highlight:
points = some_processing(im);
Where points is a matrix the same size as im with ones in the interesting points.
Now I want to draw a circle on the image in all the places where points is 1.
Is there any function in MATLAB that does this? The best I can come up with is:
[x_p, y_p] = find (points);
[x, y] = meshgrid(1:size(im,1), 1:size(im,2))
r = 5;
circles = zeros(size(im));
for k = 1:length(x_p)
circles = circles + (floor((x - x_p(k)).^2 + (y - y_p(k)).^2) == r);
end
% normalize circles
circles = circles/max(max(circles));
output = im + circles;
imshow(output)
This seems more than somewhat inelegant. Is there a way to draw circles similar to the line function?
You could use the normal PLOT command with a circular marker point:
[x_p,y_p] = find(points);
imshow(im); %# Display your image
hold on; %# Add subsequent plots to the image
plot(y_p,x_p,'o'); %# NOTE: x_p and y_p are switched (see note below)!
hold off; %# Any subsequent plotting will overwrite the image!
You can also adjust these other properties of the plot marker: MarkerEdgeColor, MarkerFaceColor, MarkerSize.
If you then want to save the new image with the markers plotted on it, you can look at this answer I gave to a question about maintaining image dimensions when saving images from figures.
NOTE: When plotting image data with IMSHOW (or IMAGE, etc.), the normal interpretation of rows and columns essentially becomes flipped. Normally the first dimension of data (i.e. rows) is thought of as the data that would lie on the x-axis, and is probably why you use x_p as the first set of values returned by the FIND function. However, IMSHOW displays the first dimension of the image data along the y-axis, so the first value returned by FIND ends up being the y-coordinate value in this case.
This file by Zhenhai Wang from Matlab Central's File Exchange does the trick.
%----------------------------------------------------------------
% H=CIRCLE(CENTER,RADIUS,NOP,STYLE)
% This routine draws a circle with center defined as
% a vector CENTER, radius as a scaler RADIS. NOP is
% the number of points on the circle. As to STYLE,
% use it the same way as you use the rountine PLOT.
% Since the handle of the object is returned, you
% use routine SET to get the best result.
%
% Usage Examples,
%
% circle([1,3],3,1000,':');
% circle([2,4],2,1000,'--');
%
% Zhenhai Wang <zhenhai#ieee.org>
% Version 1.00
% December, 2002
%----------------------------------------------------------------
Funny! There are 6 answers here, none give the obvious solution: the rectangle function.
From the documentation:
Draw a circle by setting the Curvature property to [1 1]. Draw the circle so that it fills the rectangular area between the points (2,4) and (4,6). The Position property defines the smallest rectangle that contains the circle.
pos = [2 4 2 2];
rectangle('Position',pos,'Curvature',[1 1])
axis equal
So in your case:
imshow(im)
hold on
[y, x] = find(points);
for ii=1:length(x)
pos = [x(ii),y(ii)];
pos = [pos-0.5,1,1];
rectangle('position',pos,'curvature',[1 1])
end
As opposed to the accepted answer, these circles will scale with the image, you can zoom in an they will always mark the whole pixel.
Hmm I had to re-switch them in this call:
k = convhull(x,y);
figure;
imshow(image); %# Display your image
hold on; %# Add subsequent plots to the image
plot(x,y,'o'); %# NOTE: x_p and y_p are switched (see note below)!
hold off; %# Any subsequent plotting will overwrite the image!
In reply to the comments:
x and y are created using the following code:
temp_hull = stats_single_object(k).ConvexHull;
for k2 = 1:length(temp_hull)
i = i+1;
[x(i,1)] = temp_hull(k2,1);
[y(i,1)] = temp_hull(k2,2);
end;
it might be that the ConvexHull is the other way around and therefore the plot is different. Or that I made a mistake and it should be
[x(i,1)] = temp_hull(k2,2);
[y(i,1)] = temp_hull(k2,1);
However the documentation is not clear about which colum = x OR y:
Quote: "Each row of the matrix contains the x- and y-coordinates of one vertex of the polygon. "
I read this as x is the first column and y is the second colum.
In newer versions of MATLAB (I have 2013b) the Computer Vision System Toolbox contains the vision.ShapeInserter System object which can be used to draw shapes on images. Here is an example of drawing yellow circles from the documentation:
yellow = uint8([255 255 0]); %// [R G B]; class of yellow must match class of I
shapeInserter = vision.ShapeInserter('Shape','Circles','BorderColor','Custom','CustomBorderColor',yellow);
I = imread('cameraman.tif');
circles = int32([30 30 20; 80 80 25]); %// [x1 y1 radius1;x2 y2 radius2]
RGB = repmat(I,[1,1,3]); %// convert I to an RGB image
J = step(shapeInserter, RGB, circles);
imshow(J);
With MATLAB and Image Processing Toolbox R2012a or newer, you can use the viscircles function to easily overlay circles over an image. Here is an example:
% Plot 5 circles at random locations
X = rand(5,1);
Y = rand(5,1);
% Keep the radius 0.1 for all of them
R = 0.1*ones(5,1);
% Make them blue
viscircles([X,Y],R,'EdgeColor','b');
Also, check out the imfindcircles function which implements the Hough circular transform. The online documentation for both functions (links above) have examples that show how to find circles in an image and how to display the detected circles over the image.
For example:
% Read the image into the workspace and display it.
A = imread('coins.png');
imshow(A)
% Find all the circles with radius r such that 15 ≤ r ≤ 30.
[centers, radii, metric] = imfindcircles(A,[15 30]);
% Retain the five strongest circles according to the metric values.
centersStrong5 = centers(1:5,:);
radiiStrong5 = radii(1:5);
metricStrong5 = metric(1:5);
% Draw the five strongest circle perimeters.
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');
Here's the method I think you need:
[x_p, y_p] = find (points);
% convert the subscripts to indicies, but transposed into a row vector
a = sub2ind(size(im), x_p, y_p)';
% assign all the values in the image that correspond to the points to a value of zero
im([a]) = 0;
% show the new image
imshow(im)

Resources