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)
Related
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.
I'd like to take in an RGB image, find the points in the image that are white, and get the cartesian coordinates of those points in the image. I've gotten most of the way there, but when I try to plot the cartesian coordinates, I get a vertically tiled image (i.e. 5 overlapped copies of what I should see). Anyone know what could be causing this?
,
Code: (JPG comes in as 2448 x x3264 x 3 uint8)
I = imread('IMG_0245.JPG');
imshow(I); % display unaltered image
% Convert image to grayscale
I = rgb2gray(I);
% Convert image to binary (black/white)
I = im2bw(I, 0.9);
% Generate cartesian coordinates of image
imageSize = size(I);
[x, y] = meshgrid( 1:imageSize(1), 1:imageSize(2) );
PerspectiveImage = [x(:), y(:), I(:)];
% Get indices of white points only
whiteIndices = find(PerspectiveImage(:,3));
figure; plot( PerspectiveImage(whiteIndices, 1), PerspectiveImage(whiteIndices, 2),'.');
% Flip vertically to correct indexing vs. plotting issue
axis ij
Very simple. You're declaring your meshgrid wrong. It should be:
[x, y] = meshgrid( 1:imageSize(2), 1:imageSize(1) );
The first parameter denotes the horizontal extents of the 2D grid, and so you want to make this vary for as many columns as you have. Similarly, the second parameter denotes the vertical extents of the 2D grid, and so you want to make this for as many rows as you have.
I had to pre-process some of your image to get some good results because your original image had a large white border surrounding the image. I had to remove this border by removing all pure white pixels. I also read in the image directly from StackOverflow:
I = imread('http://s7.postimg.org/ovb53w4ff/Track_example.jpg');
mask = all(I == 255, 3);
I = bsxfun(#times, I, uint8(~mask));
This was the image I get after doing my pre-processing:
Once I do this and change your meshgrid call, I get this:
How can I change the values of the R, G and B in an image manually using MATLAB?
The computation for a green color enhancement needs to be done so how do we access and change the values of RGB using MATLAB?
Assuming you are using imread to read in the image, an RGB image is stored as an M x N x 3 matrix, where M,N are the rows and columns of the image. This is essentially a 3D matrix, where each colour plane is in a particular dimension. The red plane is the first of the third dimensions, the green plane is the second, and the blue plane is the third. As such, you can do something like:
im = imread('onion.png'); % // Built-in to MATLAB
red = im(:,:,1); %// Red channel
green = im(:,:,2); % // Green channel
blue = im(:,:,3); % // Blue channel
You can also merge the planes back by doing: im2 = cat(3, red, green, blue); Now, you can manipulate any of these planes by themselves. If you want to grab a subset of the image, you can do:
imSubset = im(row1:row2, col1:col2, :);
This will grab all pixels between rows row1 to row2 and columns col1 to col2. You can then split up the image into their corresponding planes.
Now, if you want to manually change pixels, you simply access whichever rows and columns you want in each of the planes and set them to whatever you want. For example, if you wanted to set a particular region in your image to all yellow pixels, you can do this:
im(1:50,1:50,1) = 0;
im(1:50,1:50,2) = 255;
im(1:50,1:50,3) = 255;
imshow(im);
This should place a yellow square of 50 pixels wide in the top left corner. You can also do the subset approach by:
imSubset = im(1:50,1:50,:); %// Extract
imSubset(:,:,1) = 0; %// Set
imSubset(:,:,2) = 255;
imSubset(:,:,3) = 255;
im(1:50,1:50,:) = imSubset; %// Place back
If I can be a shameless promoter, take a look at my Introduction to Digital Image Processing using MATLAB slides - http://www.slideshare.net/rayryeng1/introduction-to-digital-image-processing-using-matlab
Good luck!
A biologist friend of mine asked me if I could help him make a program to count the squama (is this the right translation?) of lizards.
He sent me some images and I tried some things on Matlab. For some images it's much harder than other, for example when there are darker(black) regions. At least with my method. I'm sure I can get some useful help here. How should I improve this? Have I taken the right approach?
These are some of the images.
I got the best results by following Image Processing and Counting using MATLAB. It's basically turning the image into Black and white and then threshold it. But I did add a bit of erosion.
Here's the code:
img0=imread('C:...\pic.png');
img1=rgb2gray(img0);
%The output image BW replaces all pixels in the input image with luminance greater than level with the value 1 (white) and replaces all other pixels with the value 0 (black). Specify level in the range [0,1].
img2=im2bw(img1,0.65);%(img1,graythresh(img1));
imshow(img2)
figure;
%erode
se = strel('line',6,0);
img2 = imerode(img2,se);
se = strel('line',6,90);
img2 = imerode(img2,se);
imshow(img2)
figure;
imshow(img1, 'InitialMag', 'fit')
% Make a truecolor all-green image. I use this later to overlay it on top of the original image to show which elements were counted (with green)
green = cat(3, zeros(size(img1)),ones(size(img1)), zeros(size(img1)));
hold on
h = imshow(green);
hold off
%counts the elements now defined by black spots on the image
[B,L,N,A] = bwboundaries(img2);
%imshow(img2); hold on;
set(h, 'AlphaData', img2)
text(10,10,strcat('\color{green}Objects Found:',num2str(length(B))))
figure;
%this produces a new image showing each counted element and its count id on top of it.
imshow(img2); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for k=1:length(B),
boundary = B{k};
cidx = mod(k,length(colors))+1;
plot(boundary(:,2), boundary(:,1), colors(cidx),'LineWidth',2);
%randomize text position for better visibility
rndRow = ceil(length(boundary)/(mod(rand*k,7)+1));
col = boundary(rndRow,2); row = boundary(rndRow,1);
h = text(col+1, row-1, num2str(L(row,col)));
set(h,'Color',colors(cidx),'FontSize',14,'FontWeight','bold');
end
figure;
spy(A);
And these are some of the results. One the top-left corner you can see how many were counted.
Also, I think it's useful to have the counted elements marked in green so at least the user can know which ones have to be counted manually.
There is one route you should consider: watershed segmentation. Here is a quick and dirty example with your first image (it assumes you have the IP toolbox):
raw=rgb2gray(imread('lCeL8.jpg'));
Icomp = imcomplement(raw);
I3 = imhmin(Icomp,20);
L = watershed(I3);
%%
imagesc(L);
axis image
Result shown with a colormap:
You can then count the cells as follows:
count = numel(unique(L));
One of the advantages is that it can be directly fed to regionprops and give you all the nice details about the individual 'squama':
r=regionprops(L, 'All');
imshow(raw);
for k=2:numel(r)
if r(k).Area>100 % I chose 100 to filter out the objects with a small are.
rectangle('Position',r(k).BoundingBox, 'LineWidth',1, 'EdgeColor','b', 'Curvature', [1 1]);
end
end
Which you could use to monitor over/under segmentation:
Note: special thanks to #jucestain for helping with the proper access to the fields in the r structure here
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)