Reputation: 309
Following a question about Hu moments and a question regarding object Ellipse Variance I used the code from this link to try to calculate ellipticity based on the moment invariants like in the image below (Based on A Beginner’s Guide to Image Shape Feature Extraction Techniques). I the code I used (only checking the first 2 objects) I do not get a value close to 1 (which should indicate an Ellipticity) when I have an ellipse object. Can someone please explain what I did wrong?
code:
clc;
clear;
close all;
% Image processing
I= rgb2gray(imread('https://az877327.vo.msecnd.net/~/media/images/products/2005/other/mipix%20ellipses%20full%20frame.jpg?v=1&h=550&w=800&crop=1'));
bw = imbinarize(I);
bw = imfill(bw,'holes');
bw = bwareaopen(bw, 100);
imshow(bw)
hold on;
[B,L] = bwboundaries(bw,'noholes');
stats = regionprops(L,'Centroid','Image');
%Loop - data acquisition
for i = 1 : 2 %numel(stats)
b = B{i};
c = stats(i).Centroid;
f = stats(i).Image;
y = b(:,1);
x = b(:,2);
plot( b(:,2),b(:,1),'Color','red','linewidth',1);
text(c(1),c(2),num2str(i),'Color','red');
%based on https://raw.githubusercontent.com/dipum/dipum-toolbox/master/dipum/invmoments.m
[M,N] = size(f);
[x,y] = meshgrid(1:N,1:M);
% Turn x,y, and F into column vectors to make the summations a bit
% easier to compute in the following.
x = x(:);
y = y(:);
f = f(:);
% DIPUM3E equation (13-27)
m.m00 = sum(f);
% Protect against divide-by-zero warnings.
if (m.m00 == 0)
m.m00 = eps;
end
% The other central moments:
m.m10 = sum(x .* f);
m.m01 = sum(y .* f);
m.m11 = sum(x .* y .* f);
m.m20 = sum(x.^2 .* f);
m.m02 = sum(y.^2 .* f);
m.m30 = sum(x.^3 .* f);
m.m03 = sum(y.^3 .* f);
m.m12 = sum(x .* y.^2 .* f);
m.m21 = sum(x.^2 .* y .* f);
% DIPUM3E equations (13-28) through (13-30).
xbar = m.m10 / m.m00;
ybar = m.m01 / m.m00;
e.eta11 = (m.m11 - ybar*m.m10) / m.m00^2;
e.eta20 = (m.m20 - xbar*m.m10) / m.m00^2;
e.eta02 = (m.m02 - ybar*m.m01) / m.m00^2;
e.eta30 = (m.m30 - 3 * xbar * m.m20 + 2 * xbar^2 * m.m10) / ...
m.m00^2.5;
e.eta03 = (m.m03 - 3 * ybar * m.m02 + 2 * ybar^2 * m.m01) / ...
m.m00^2.5;
e.eta21 = (m.m21 - 2 * xbar * m.m11 - ybar * m.m20 + ...
2 * xbar^2 * m.m01) / m.m00^2.5;
e.eta12 = (m.m12 - 2 * ybar * m.m11 - xbar * m.m02 + ...
2 * ybar^2 * m.m10) / m.m00^2.5;
% DIPUM3E Table 13.8.
phi(1) = e.eta20 + e.eta02;
phi(2) = (e.eta20 - e.eta02)^2 + 4*e.eta11^2;
phi(3) = (e.eta30 - 3*e.eta12)^2 + (3*e.eta21 - e.eta03)^2;
phi(4) = (e.eta30 + e.eta12)^2 + (e.eta21 + e.eta03)^2;
phi(5) = (e.eta30 - 3*e.eta12) * (e.eta30 + e.eta12) * ...
( (e.eta30 + e.eta12)^2 - 3*(e.eta21 + e.eta03)^2 ) + ...
(3*e.eta21 - e.eta03) * (e.eta21 + e.eta03) * ...
( 3*(e.eta30 + e.eta12)^2 - (e.eta21 + e.eta03)^2 );
phi(6) = (e.eta20 - e.eta02) * ( (e.eta30 + e.eta12)^2 - ...
(e.eta21 + e.eta03)^2 ) + ...
4 * e.eta11 * (e.eta30 + e.eta12) * (e.eta21 + e.eta03);
phi(7) = (3*e.eta21 - e.eta03) * (e.eta30 + e.eta12) * ...
( (e.eta30 + e.eta12)^2 - 3*(e.eta21 + e.eta03)^2 ) + ...
(3*e.eta12 - e.eta30) * (e.eta21 + e.eta03) * ...
( 3*(e.eta30 + e.eta12)^2 - (e.eta21 + e.eta03)^2 );
disp('Object number:');
disp(i);
Is = (m.m20 * m.m02-m.m11^2)/m.m00^4;
Em1= 16*pi^2*Is
Em2= (16*pi^2*Is)^-1
min(Em1, Em2)
end
Upvotes: 0
Views: 332
Reputation: 16811
As I said in the comments, you need to use the central moments rather than raw moments as your code is doing. See Measuring Shape: Ellipticity, Rectangularity, and Triangularity
Removing the unnecessary calculations for eta
and phi
, the last part of your code should be:
% Calculate Raw Moments:
m.m10 = sum(x .* f);
m.m01 = sum(y .* f);
m.m11 = sum(x .* y .* f);
m.m20 = sum(x.^2 .* f);
m.m02 = sum(y.^2 .* f);
m.m30 = sum(x.^3 .* f);
m.m03 = sum(y.^3 .* f);
m.m12 = sum(x .* y.^2 .* f);
m.m21 = sum(x.^2 .* y .* f);
% DIPUM3E equations (13-28) through (13-30).
xbar = m.m10 / m.m00;
ybar = m.m01 / m.m00;
% Calculate Central Moments:
m.mu11 = m.m11 - xbar*m.m01;
m.mu20 = m.m20 - xbar*m.m10;
m.mu02 = m.m02 - ybar*m.m01;
disp('Object number:');
disp(i);
Is = (m.mu20 * m.mu02 - m.mu11^2)/m.m00^4;
Em1= 16*pi^2*Is
Em2= (16*pi^2*Is)^-1
min(Em1, Em2)
With these changes, the results for the first two objects are:
Object number:
1
Em1 = 1.000005232603003
Em2 = 9.999947674243773e-01
ans = 9.999947674243773e-01
Object number:
2
Em1 = 9.999818710527637e-01
Em2 = 1.000018129275901
ans = 9.999818710527637e-01
Upvotes: 2