Counting number of edge pixels in matlab - image

I want to count the number of edge pixels in a given image. I tried it by counting pixels of white color of the image we get by using Canny operator on the image.
I = rgb2gray(imread('replay1.jpg'));
bw = edge(I,'canny');
numberOfBins = 256;
[r, cl, x] = size(bw);
[pixelCount, grayLevels] = imhist(bw);
c = sum(pixelCount(pixelCount==255));
disp(c*100/(r*cl));
Questions:
1. But this somehow gives the same answer for all images, which suggests I am doing it wrong. How should I find number of edge pixels of an image in matlab?
2. Also can I use canny operator on YCbCr format of an image? I tried doing that but it gives me errors.

PART 1
Use this - count_edge_pixels = nnz(bw) This is a very efficient way to calculate true (1) values that are edge pixels in this case and thus, would give you count of edge/white pixels as calculated from edge.
PART 2
You can use edge on each of Y, Cb, Cr separately or just use Y for edge detection on the luminance part. Use this to get YCbCr from RGB images.
Let's suppose you would like to get edge information on the luminance map of the image, do something like this -
YCBCR = rgb2ycbcr(imread('replay1.jpg'));
luminance_map = YCBCR(:,:,1);
bw = edge(luminance_map,'canny');
Hope this makes sense and works for you!

pixelCount(2) will give you the number of edge pixels here. As #Divakar mentioned, nnz(bw) will also work as expected.
I = rgb2gray(imread('test.jpg'));
bw = edge(I,'canny');
numberOfBins = 256;
[r, cl, x] = size(bw);
[pixelCount, grayLevels] = imhist(bw);
count = pixelCount(2); // <- here, or use "count = nnz(bw)"
To detect canny edges on YCbCr images, you can use edgecolor.m.

This is also efficient way to count the num of edge pixels.
count =length(find(BW(:)==1));

Related

How to apply Thresholding in image processing

This is sample code for K means algorithm.
k = 5;
[Centroid,new_cluster]=kmeans_algorithm(inv_trans_img,k);
for i_loop = 1:k
cluster = zeros(size(inv_trans_img));
pos = find(new_cluster==i_loop);
cluster(pos) = new_cluster(pos);
figure; imshow(cluster,[]);title('K-means');
end
I need to get the final image from this K means algorithm and I need to pass that image for thresholding process.I did it like below.
tumour_image=cluster;
n = 512;
binarized_img = zeros(n,n);
sort_val = sort(tumour_image(:));
mid_val = ceil(length(sort_val)/2);
threshold = tumour_image(mid_val);
binarized_img(find(tumour_image>=threshold)) = 1;
binarized_img(find(tumour_image<threshold)) = 0;
imshow(binarized_img);title('binarized image');
But now the problem is,only a white image is coming as a result.How can i solve this out.
Your threshold should be:
threshold = sort_val(mid_val);
You need to get the median of the sorted values, not the center element of tumour_image.
As #NeilSlater mentions in the comments, the reason that you're getting an all-white image from your existing code is that you are, by chance, selecting a black pixel from the original image, so when you threshold, the entire image is greater than or equal to that pixel in value.
In the case of images in which the majority of the pixels are 0, this will still give you an all-white image as as result. One way around this, and the most analogous to what you're currently doing, is to take the median of the nonzero pixels.
mid_val = ceil((find(sort_val, 1)+length(sort_val))/2);
Alternatively, if you know which clusters you're interested in you can simply keep only those clusters.
binarized_image = tumour_image >= 3; % keep clusters 3 and above

Matlab detect rectangle from image [duplicate]

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.

Are there MATLAB scripts that will give me a quantitative/visual depiction of all the colors in an image?

I have tried the following:
b=imread('/home2/s163720/lebron.jpg');
hsv = rgb2hsv(b);
h = hsv(:,:,1);
imhist(h,16)
However, it does not give me quite what I'm looking for. It would be great to see a counter of some sort for different hues, or maybe even a distribution of the colors.
This would be greatly appreciated.
I think this may be on the line of what you're looking for.
%Read the image
img = imread('/home2/s163720/lebron.jpg');
%convert to hsv and reshap to a N x 3 matrix
hsv = rgb2hsv(img);
hsv2 = squeeze(reshape(hsv, [], 1, 3));
%Extract hue (and convert to an angle) and saturation
Hue = 2*pi*hsv2(:,1);
Saturation = hsv2(:,2);
%The number of bins in the hue and saturation directions
RadialColorBins = 50;
AngularColorBins = 50;
%Where the edged of the bins are
edges = {linspace(0, 1, RadialColorBins), linspace(0, 2*pi, AngularColorBins) - 2*pi / AngularColorBins};
%bin the data
[heights,centers] = hist3([Saturation, Hue],'Edges',edges);
%Extract the centers
radius = centers{1};
angle = centers{2};
%Force periodicity
angle = [angle, angle(1)];
heights = [heights, heights(:, 1)]';
%Mesh the r and theta components
[Radius, Angle] = meshgrid(radius, angle);
%Make a color map for the polar plot
CMap = hsv2rgb(Angle/(2*pi), Radius, ones(size(Radius)));
figure(1)
imshow(img)
%polar histogram in s-h space
figure(2)
surf(Radius.*cos(Angle), Radius.*sin(Angle), heights, CMap,'EdgeColor','none');
I know this is supposed to be where the answers should be, but I am quite sure that there is not a generic answer for your question. However there are a couple of possibilities, maybe you or anyone else can come up with more.
So the basic problem as you want a histogram, is that you have to choose some representation of the color as a single number. Which is quite a difficult problem.
The first solution could be to transform the rgb color to wavelength, and then ignore the intensity of the image. The problem by using this idea is that the rgb colors defines more colors than on wavelength alone. see: http://jp.mathworks.com/matlabcentral/newsreader/view_thread/313712
A second solution could be to define a number as A = sum(rgb.*[1,10,100]); and then use this number as your representation of the color.
A third solution would be to transform the hexadecimal representation of the number to a decimal representation and then use this number.
Once you have a representation for every color of every pixel, you simply reshape the matrix into a vector and use the standard hist command to plot it. But as mentioned, mayby someone has a better idea for a representation of the color as a single number.

Discarding everything above a slanted line in an image

I am trying to discard (i.e. zero out) all of the pixels above a certain region in an image (for example, a clearly defined white bar). Is there any way I can use the result of a Sobel edge detection to accomplish this, or is there a better way?
You could try something like this:
I = imread('image.png'); % read image
E = edge(I) % get results of canny edge detector
[~,idx] = max( sum(E,2:) ); % find the row with the clearest horizontal edge
I(1:idx-1,:) = 0; % zero everything above (not including) that row
You could probably replace the canny edge image with a Sobel image and get the same results.

How to compute horizontal gradient value?

So I want to measure the vertical edges of an image to use it later as depth cue for 2D to 3D conversion.
To do so I will have to compute the horizontal gradient value for each block to measure the vertical edges as follow:
̅ g(x,y) = 1/N ∑_((x',y')∈ Ω(x,y))〖g(x', y')〗
Where:
g(x',y') is a horizontal gradient at a pixel location (x',y'),
omega(x,y) is the nighborhood of the pixel location(x',y')
and N is the number of pixels in omega(x,y).
So Here is what I did on matlab:
I = im2double(imread('landscape.jpg'));
% convert RGB to gray
gI = rgb2gray(I);
[nrow, ncol] = size(gI);
% divide the image into 4-by-4 blocks
gI = mat2tiles((gI),[4,4]);
N = 4*4; % block size
% For each block, compute the horizontal gradient
gI = reshape([gI{:}],4*4, []);
mask = fspecial('sobel');
g = imfilter(gI, mask);
g_bar = g./N;
g_bar = reshape(g_bar,nrow, ncol);
I'm new to Matlab so I'm not sure if my code is expressing the equation in the right way.
Can you please let me know if you think it is correct? as I'm not sure how to test the output!
There's no need for you to decompose your image into 4 x 4 blocks. The horizontal gradient can be used with a Sobel filter or Prewitt filter, which is 3 x 3 and can directly be put into imfilter. imfilter performs 2D convolution / filtering with a specified mask / kernel for you, so tiling is not necessary. As such, you can just use imfilter with the mask defined through fspecial, and define N = 9. Therefore:
I = im2double(imread('landscape.jpg'));
% convert RGB to gray
gI = rgb2gray(I);
N = 9;
mask = fspecial('sobel');
g = imfilter(gI, mask);
g_bar = g./N;
From experience, increasing the size of your gradient mask won't give you much better results. You want to ensure that the mask is as small as possible to capture as many local changes as possible.

Resources