This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I visualize a matrix with colors and values displayed?
I basically have a NxN (edit:N can be up to 80) matrix of double in MATLAB and I when to plot it as an array (I want to see the numbers) and some of the cells should be colored (the function to decide how I color my numbers is independent from the numbers).
I have thought of different ways to do that :
create an grid as an image and overlay it with the text but the plot of MATLAB is going to be horrible as it will remove some pixels to resize the image (my matrix can be around 80x80).
Export to excel ? Don't know how I would color the cells though.
Any help ?
As an image is sometimes more helpful :
Consider the following code:
%# matrix
M = rand(11,11);
[r c] = size(M);
%# text location and labels
[xloc yloc] = meshgrid(1:c,1:r);
xloc = xloc(:); yloc = yloc(:);
str = strtrim(cellstr( num2str(M(:),'%.3g') ));
xticklabels = cellstr( num2str((1:c)','M%d') );
yticklabels = cellstr( num2str((1:r)','M%d') );
%# plot colored cells
mask = M>0.9; %# or any other mask
h = imagesc(1:c, 1:r, ones(size(M)));
set(h, 'AlphaData',mask)
colormap(summer) %# colormap([0 1 0])
set(gca, 'Box','on', 'XAxisLocation','top', 'YDir','reverse', ...
'XLim',[0 c]+0.5, 'YLim',[0 r]+0.5, 'TickLength',[0 0], ...
'XTick',1:c, 'YTick',1:r, ...
'XTickLabel',xticklabels, 'YTickLabel',yticklabels, ...
'LineWidth',2, 'Color','none', ...
'FontWeight','bold', 'FontSize',8, 'DataAspectRatio',[1 1 1]);
%# plot grid
xv1 = repmat((2:c)-0.5, [2 1]); xv1(end+1,:) = NaN;
xv2 = repmat([0.5;c+0.5;NaN], [1 r-1]);
yv1 = repmat([0.5;r+0.5;NaN], [1 c-1]);
yv2 = repmat((2:r)-0.5, [2 1]); yv2(end+1,:) = NaN;
line([xv1(:);xv2(:)], [yv1(:);yv2(:)], 'Color','k', 'HandleVisibility','off')
%# plot text
text(xloc, yloc, str, 'FontSize',8, 'HorizontalAlignment','center');
As you increase the size of the matrix, the text will eventually overlap...
EDIT
Here is a way that works with larger matrices: we use an invisible figure, resize it to something big enough, and use a small font size (I used 2):
M = rand(80,80);
figure('visible','off')
set(gcf, 'Units','Pixels', 'Position', [0, 0, 10000, 10000], ...
'PaperPositionMode','Auto');
set(gca, 'units','normalized', 'position',[0.05 0.02 0.9 0.95])
%# ...
Then at the end, export to file with a high resolution:
%# ...
print -dpng -r600 file.png
You can see the output file here (10025x5962 image, 645KB)
If you are willing to output to html (typically using matlab's publish ability), you can modify one of many html table functions on the file exchange to suit your needs. Here is one example. This will enable you to output text as well as colors.
http://www.mathworks.com/products/matlab/demos.html?file=/products/demos/shipping/matlab/imagedemo.html ?
Then you can try to write text on it
In Excel you can always use conditional formatting, no problems there.
As far as matlab goes, I've never done something like it (although the idea has crossed my mind). Did you have in mind something like this How do I visualize a matrix with colors and values displayed?
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 need to know how to align an image in Matlab for further work.
for example I have the next license plate image and I want to recognize all
the digits.
my program works for straight images so, I need to align the image and then
preform the optical recognition system.
The method should be as much as universal that fits for all kinds of plates and in all kinds of angles.
EDIT: I tried to do this with Hough Transform but I didn't Succeed. anybody can help me do to this?
any help will be greatly appreciated.
The solution was first hinted at by #AruniRC in the comments, then implemented by #belisarius in Mathematica. The following is my interpretation in MATLAB.
The idea is basically the same: detect edges using Canny method, find prominent lines using Hough Transform, compute line angles, finally perform a Shearing Transform to align the image.
%# read and crop image
I = imread('http://i.stack.imgur.com/CJHaA.png');
I = I(:,1:end-3,:); %# remove small white band on the side
%# egde detection
BW = edge(rgb2gray(I), 'canny');
%# hough transform
[H T R] = hough(BW);
P = houghpeaks(H, 4, 'threshold',ceil(0.75*max(H(:))));
lines = houghlines(BW, T, R, P);
%# shearing transforma
slopes = vertcat(lines.point2) - vertcat(lines.point1);
slopes = slopes(:,2) ./ slopes(:,1);
TFORM = maketform('affine', [1 -slopes(1) 0 ; 0 1 0 ; 0 0 1]);
II = imtransform(I, TFORM);
Now lets see the results
%# show edges
figure, imshow(BW)
%# show accumlation matrix and peaks
figure, imshow(imadjust(mat2gray(H)), [], 'XData',T, 'YData',R, 'InitialMagnification','fit')
xlabel('\theta (degrees)'), ylabel('\rho'), colormap(hot), colorbar
hold on, plot(T(P(:,2)), R(P(:,1)), 'gs', 'LineWidth',2), hold off
axis on, axis normal
%# show image with lines overlayed, and the aligned/rotated image
figure
subplot(121), imshow(I), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'g.-', 'LineWidth',2);
end, hold off
subplot(122), imshow(II)
In Mathematica, using Edge Detection and Hough Transform:
If you are using some kind of machine learning toolbox for text recognition, try to learn from ALL plates - not only aligned ones. Recognition results should be equally well if you transform the plate or dont, since by transforming, no new informations according to the true number will enhance the image.
If all the images have a dark background like that one, you could binarize the image, fit lines to the top or bottom of the bright area and calculate an affine projection matrix from the line gradient.
I have the following image on which i have applied bilateral filtering and subtracted it from my original image
Is it possible to outline the glass defect as shown
After apply Hough i got the following result not perfect :/
My matlab code :
im = imread('C:\Users\SUJIT\Desktop\image003.jpg');
im=rgb2gray(im);
h = fspecial('gaussian', size(im), 1.0);
g = imfilter(im, h);
im=im2double(g);
im=imadjust(im);
imgauss = imfilter(im, fspecial('gaussian',[7 7], 6),'conv');
imbi = bilateralfilter(im, [5 5], 3, 3);
imbi= im - imbi;
imshow(imbi,[]); title('Bilateral Filted Image');
I = imcrop(imbi, [30 30 450 350]);
J = imfilter(I, fspecial('gaussian', [17 17], 5), 'symmetric');
BW = edge(J, 'canny');
%# Hough Transform and show matrix
[H T R] = hough(BW);
imshow(imadjust(mat2gray(H)), [], 'XData',T, 'YData',R, ...
'InitialMagnification','fit')
xlabel('\theta (degrees)'), ylabel('\rho')
axis on, axis normal, hold on
colormap(hot), colorbar
%# detect peaks
P = houghpeaks(H, 10);
plot(T(P(:,2)), R(P(:,1)), 'gs', 'LineWidth',2);
%# detect lines and overlay on top of image
lines = houghlines(BW, T, R, P);
figure, imshow(I), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'g.-', 'LineWidth',2);
end
hold off
Please help am i doing something wrong here?
It is a bit hard to give a general answer based on only one image and no other information, but I can give a specific answer based on your sample image.
Assuming that what you want to find is the vertical blurry line in the middle of the image, this my approach. I won't go into specific implementation details, but only an outline on how I would do it.
Find the windows. There are multiple approaches to this. Some ideas are to either find the corners, or to find the rectangular structure itself. The Hough transform is a possible tool.
For each window, check if there are vertical structures in it.
After I did a 'imclearborder', there are still a bit of unwanted object around the barcode. How can I remove those objects to isolate the barcode? I have pasted my code for your reference.
rgb = imread('barcode2.jpg');
% Resize Image
rgb = imresize(rgb,0.33);
figure(),imshow(rgb);
% Convert from RGB to Gray
Igray = double(rgb2gray(rgb));
% Calculate the Gradients
[dIx, dIy] = gradient(Igray);
B = abs(dIx) - abs(dIy);
% Low-Pass Filtering
H = fspecial('gaussian', 20, 10);
C = imfilter(B, H);
C = imclearborder(C);
figure(),imagesc(C);colorbar;
Well, i have already explained it in your previous question How to find the location of red region in an image using MATLAB? , but with a opencv code and output images.
Instead of asking for code, try to implement it yourself.
Below is what to do next.
1) convert image 'C' in your code to binary.
2) Apply some erosion to remove small noises.( this time, barcode region also shrinks)
3) Apply dilation to compensate previous erosion.(most of noise will have removed in previous erosion. So they won't come back)
4) Find contours in the image.
5) Find their area. Most probably, contour which has maximum area will be the barcode, because other things like letters, words etc will be small ( you can understand it in the grayscale image you have provided)
6) Select contour with max. area. Draw a bounding rectangle for it.
Its result is already provided in your previous question. It works very nice. Try to implement it yourself with help of MATLAB documentation. Come here only when you get an error which you don't understand.
%%hi, i am ading my code to yours at the end of your code%%%%
clear all;
rgb = imread('barcode.jpeg');
% Resize Image
rgb = imresize(rgb,0.33);
figure(),imshow(rgb);
% Convert from RGB to Gray
Igray = double(rgb2gray(rgb));
Igrayc = Igray;
% Calculate the Gradients
[dIx, dIy] = gradient(Igray);
B = abs(dIx) - abs(dIy);
% Low-Pass Filtering
H = fspecial('gaussian', 10, 5);
C = imfilter(B, H);
C = imclearborder(C);
imshow(Igray,[]);
figure(),imagesc(C);colorbar;
%%%%%%%%%%%%%%%%%%%%%%%%from here my code starts%%%%%%%%%%%%%%%%
bw = im2bw(C);%%%binarising the image
% imshow(bw);
%%%%if there are letters or any other noise is present around the barcode
%%Note: the size of the noise and letters should be smaller than the
%%barcode size
labelImage = bwlabel(bw,8);
len=0;labe=0;
for i=1:max(max(labelImage))
a = find(labelImage==i);
if(len<length(a))
len=length(a);
labe=i;
end
end
imag = zeros(size(l));
imag(find(labelImage==labe))=255;
% imtool(imag);
%%%if Necessary do errossion
% se2 = strel('line',10,0);
% imag= imerode(imag,se2);
% imag= imerode(imag,se2);
[r c]= find(imag==255);
minr = min(r);
maxc = max(c);
minc = min(c);
maxr = max(r);
imag1 = zeros(size(l));
for i=minr:maxr
for j=minc:maxc
imag1(i,j)=255;
end
end
% figure,imtool(imag1);
varit = find(imag1==0);
Igrayc(varit)=0;
%%%%%result image having only barcode
imshow(Igrayc,[]);
%%%%%original image
figure(),imshow(Igray,[]);
Hope it is useful
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)