Calculating Circularity in MATLAB

I am trying to calculate Circularity using the formula (Perimeter^2)/(4 Pi Area). So, a perfect circle will have a value of 1, and deviations will range from greater than 1 to infinity. However, I am getting some values less than 1 when I run the code, which doesn't make any sense. I am calculating perimeter by getting the edge count of every boundary pixel, instead of using the perimeter function provided by regionprops. Area is from regionprops, and is just the number of total pixels. Does anyone know why this is happening?
Here is the code for the perimeter calculation:
function a = new_perim(image)
notimg = true(size(image)+2);
notimg(2:end-1, 2:end-1) = ~image;
% Find locations where a non-zero pixel is adjacent to a zero pixel,
% for each cardinal direction in turn
topedges = image & notimg(1:end-2, 2:end-1);
leftedges = image & notimg(2:end-1, 1:end-2);
bottomedges = image & notimg(3:end, 2:end-1);
rightedges = image & notimg(2:end-1, 3:end);
% Sum each set of locations separately, then add to get total perimeter
perim = sum(topedges(:)) + sum(leftedges(:)) + ...
+ sum(bottomedges(:)) + sum(rightedges(:));
a = perim;
end

2 commentaires

Star Strider
Star Strider le 17 Déc 2018
It might help if you attach a representative image, and post (or attach) your code.
Without those, we have no idea what the problem is. (This will not guarantee an Answer, but it will significantly increase the probability of one.)
eaf
eaf le 18 Déc 2018
Thank you for the suggestion! I edited the question so that it contains the code.

Connectez-vous pour commenter.

Réponses (1)

John D'Errico
John D'Errico le 17 Déc 2018
Modifié(e) : John D'Errico le 17 Déc 2018

0 votes

For a circle, perimeter = 2*pi*r. area = pi*r^2.
So the ratio you pose is indeed 1 for a circle. And for any other region, that ratio SHOULD exceed 1, that is, if you computed things correctly.
Consider a region, where this computation yields a value lower than 1. That can only possibly happen if the area is too large compared to the perimeter, or if the computed perimeter is too small. Remember, that you are talking pixels here.
Suppose we have a circular region that contains a number of pixels. The combined area of those pixels is easy to compute, because square pixels pack together perfectly since they tile the plane.
But what is the perimeter? How do you define the length of a pixel around that perimeter? Be careful here. Make sure that you got EVERY pixel around the perimeter. And some pixels are sitting at an angle, relative to that boundary. What is the average length of a pixel as you traverse 360 degrees around that circle? How about pixels that are only partially on the boundary?
The point is, I would bet that your computation of the perimeter may be slightly inaccurate, even for a nicely "circular" region. So, while your formula is correct in an abstract mathematical sense, it is flawed when you interpret it in terms of pixels. That imit of 1 as a minimum may be only an approximate limit.

6 commentaires

eaf
eaf le 18 Déc 2018
Can you clarify what you mean by "some pixels are sitting at an angle, relative to that boundary"? And about "pixels that are only partially on the boundary"? I also added the code I am using to calculate the perimeter to my original question, if that helps.
John D'Errico
John D'Errico le 18 Déc 2018
Modifié(e) : John D'Errico le 18 Déc 2018
A pixel is square. It has a size of 1 unit, when viewed parallel to an axis. However, when used as a measure of the distance around a circular boundary, at some points around that circle, it might contribute as much as a distance of sqrt(2) units around that perimeter. Or, worse, since a pixel on the perimeter of a boundary technically may expose either one, two, oreven three sides, the actual contribution of that pixel to the perimeter length will be between 1 and 3 units of length. If you assume that every pixel contributes only ONE unit of length to the perimeter, you are clearly undercounting when computing the perimeter.
The point is, when you simply count the number of "perimeter" pixels, you cannot merely assume they are all the same size, that all are are "equal".
Conversely, when you simply count pixels, adding up the area of each, since they tile the domain of interest, then they do constitute a reasonable measure of the included area, with the only issue being how well such a ragged edge approximates a circular area.
Therefore, you are tending to underestimate the perimeter, and in turn, that yields a ratio that is less than 1.
I understand that using pixels to calculate the perimeter of a circular object will have some error. However, I don't really have another method available. Also, I am not just counting the number of "perimeter" pixels - I am counting their edges. So, if I have a shape that is a square made up of four pixels, my perimeter code says the perimeter is 8 while regionprops gives the area as 4. I have calculated the perimeter of a number of different shape, and it always outputs the value that it should.
a = [0 0 0 0;0 1 1 0;0 1 1 0;0 0 0 0]
a =
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
>> new_perim(a)
ans =
8
>> regionprops(a,'Area')
ans =
struct with fields:
Area: 4
John D'Errico
John D'Errico le 19 Déc 2018
  1. If you have accurately measured both perimeter AND area for some general region, then the ratio you propose will be no less than 1. Do we agree with that statement?
  2. You have computed the perimeter and area of some general region. the indicated ratio is less than 1.
The conclusion seems pretty clear. It must reduce to one of these alternatives:
  1. Statement 1 is incorrect, or
  2. You did not compute the perimeter or area correctly, or
  3. You improperly evaluated the formula you have posed.
If we exclude alternative #3 as too trivial to worry about, then 1 or 2 are the issue.
If you trust claim 1, then you need to carefully evaluate 2. Look very carefully at an image where that perimeter was undercounted, as either the perimeter or area were incorrectly computed.
So far, you have not shown such an image. Only one where things trivially work.
Image Analyst
Image Analyst le 19 Déc 2018
I have seen this often (circularities less than 1). I chalk it up to digitization error, and I adjust the thresholds to take that into account.
John D'Errico
John D'Errico le 20 Déc 2018
Yes. The only mathematical way to get a value significantly less than 1 is to mis-estimate one of the parameters in that expression, thus area too high, or perimeter too low. If it is less than 1 by a sufficiently small amount, then you may well ignore it as just numerical error in the computations. If the discrepancy is large, then it suggests there is a mistake in the computation of one or both of those parameters, one that one might be correctable.
That said, floating point computations are not truly mathematics, but only an approximation thereof, one that is typically accurate to roughly 16 decimal digits of precision.
For example, if the ratio is computed less than 1 by an amount on the order of 1e-16, then I would know the problem is down in the least significant bits of the computation. Just ignore that out of hand, since you should never trust the least signigificant bits of a floating point number.
Even if the discrepancy is less than 1 by some still small, but larger amount? Now you might guess the error is probably in the computation of area or perimeter, that they were mis-estimated by some amount. You might decide to ignore it, because you are approximating the perimeter and area down at the pixel level.
If the reported ratio is less than 1 by a large fraction, thus perhaps you see a fraction like 0.75, when you expected 1, then something is seriously wrong in what you computed. That is, the perimeter and area numbers are out of sinc with each other, so you are not computing the perimeter of the same tiled region as that for which you computed the area.

Connectez-vous pour commenter.

Produits

Version

R2017b

Question posée :

eaf
le 17 Déc 2018

Commenté :

le 20 Déc 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by