MATLAB Answers


Counting the pixels within a circle detected in an image

Asked by Ivan
on 23 Dec 2011

Hi everyone.

Based on this image,

Using Hough Transformation, I managed to detect many circles. But I require only the middle circle detected around the pupil. There are several methods that I was thinking, that could remove the other circles.

For example,

1) counting the number of black pixels within the circle and the one with the most is the pupil. 2) taking the white pixels along the circumference of the pupil. the one with the most white pixels is the pupil.

I was thinking number 2 would be a more accurate solution. Hence, how do I count the number of white pixels?

Thank you!


2 Answers

Answer by David Young
on 23 Dec 2011
 Accepted answer

How standard are your images? Could you choose the circle whose radius and centre coordinates are within expected ranges?

If you can't do this, I'd suggest making measurements on the original image, rather than on the edge map. There have been answers here recently showing how to make measurements on the pixels in a circular disk - add a comment if you need help finding one, but do a search first.

By the way, there's a highlight which badly affects the parameters of the circle round the pupil. If you can find some way of removing it (by preprocessing prior to the edge detection perhaps) that will improve your accuracy enormously.


Rather than counting black pixels (which means defining what is "black"), why not compare the mean of the grey-levels inside the circles? Here's a function you can use to compute these means:

function m = meanDisk(img, xc, yc, r)
%meanDisk computes mean of values inside a circle
%   M = meanDisk(IMG, XC, YC, R) returns the mean of IMG(Y,X) for all X and
%   Y such that the Euclidean distance of (X,Y) from (XC,YC) is less than
%   R. IMG must be 2-D, R must be positive, and some elements of IMG must
%   lie within the circle.
% This section is for efficiency only - avoids wasting computation time on
% pixels outside the bounding square
[sy sx] = size(img);
xmin = max(1, floor(xc-r));
xmax = min(sx, ceil(xc+r));
ymin = max(1, floor(yc-r));
ymax = min(sy, ceil(yc+r));
img = img(ymin:ymax, xmin:xmax); % trim boundaries
xc = xc - xmin + 1;
yc = yc - ymin + 1;
% Make a circle mask
[x y] = meshgrid(1:size(img,2), 1:size(img,1));
mask = (x-xc).^2 + (y-yc).^2 < r.^2;
% Compute mean
m = sum(sum(double(img) .* mask)) / sum(mask(:));

EDIT Adding code to deal with the four example images linked to from Ivan's comment of 12 Jan 2012.

This assumes the use of this Hough transform from the file exchange.

The code below works for all 4 of the example images posted (though note that cropping may affect the results as the original image isn't in quite the same place in all of them). I used the fact that the pupil is dark to detect the case where the eye is closed - this works better than playing with the Hough transform parameters.

% Read in the image as downloaded, crop out the starting image, convert to
% grayscale in range 0-1
img = imread('help1.jpg'); % or whatever
img = double(rgb2gray(img(28:169, 167:391, :)))/256;
% Find edges. Note that Canny method incorporates Gaussian smoothing and
% gradient calculation, so no need to do these separately
edgeim = edge(img, 'canny');
% Detect most prominent circle. Radius range may be overgenerous.
radii = 7:2:21;
[h, margin] = circle_hough(edgeim, radii);
peak = circle_houghpeaks(h, radii, margin, 'npeaks', 1);
cx = peak(1);
cy = peak(2);
r = peak(3);
% Test whether the brightness inside the circle is greater than the average
% image brightness divided by the following constant. If it is, the pupil
% is probably not visible.
pupil_darkness_ratio = 2;
if pupil_darkness_ratio*meanDisk(img, cx, cy, r) > mean(img(:))
    disp('No pupil found');
    hold on;
    [x, y] = circlepoints(r);
    plot(x+cx, y+cy, 'g-');
    hold off


on 23 Jan 2012

yeah I was thinking I could use the axis to make an error comparison, comparing with what the system has calculated and what i can see from the axis manually. but just to confirm that the default units would be in pixels ?

Image Analyst
on 23 Jan 2012

Units of measurements are in pixels. To convert to mm you need to multiply by a conversion factor that has units of mm/pixel. You can do that by measuring a ruler and measuring a known distance in mm to see how many pixels it is. Maybe you can use improfile() for doing that.

David Young
on 23 Jan 2012

Replying to your question about using an ellipse rather than a circle. As Image Analyst says, you can readily modify the function for measuring mean graylevel to work with an ellipse, by changing the equation that generates the mask. It's also not too hard to draw an ellipse on the image.

Making the Hough Transform detect ellipses in the first place is much more work. You might find some general ellipse detection code that you could use instead of the HT for circles, but it will have the problem that it's trying to find 5 parameters. You can fit an ellipse to the pupil with only two free parameters by exploiting some constraints: there's more information in this paper:

Answer by Image Analyst
on 23 Dec 2011

I think you should look at what you said: "require only the middle circle." Now since you placed those circles, you know where the centers are. So you simply take the center that is closest to (numberOfRows/2, numberOfColumns/2). It's as simple as that, assuming the circle you want is the one closest to the middle of the image.


on 4 Jan 2012

hi Image Analyst, i have tried your demo. unfortunately it doesnt work well on my image. as it is not against a black background unlike your image.

Image Analyst
on 12 Jan 2012

I didn't give a demo. Upload your image to and your code for finding the circle locations.

on 17 Jan 2012

I have solved it by only accepting the circle that is near the original circle. thank you so much Image Analyst!

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply today