I need to find central moment of an image. The central moment is given by the equation:
where x
and y
are the spatial image co-ordinates, and are the mean x
and y
(or centroid) co-ordinates, p
and q
being integers and f(x,y)
is an image.
In addition, I want to understand how to deal with f(x,y)
because it will be holding all pixel values.
Use bsxfun
sz = size( img ); %// assuming image is gray scale - 2D array
x = ( 1:sz(2) );
y = ( 1:sz(1) ).'; %'
x = x - mean(x);
y = y - mean(y);
Mpq = sum( reshape( bsxfun( @times, bsxfun( @times, img, x.^p ), y.^q ), [], 1 ) ); %// computing the p-q moment
benchmarking:
disp('Solution of rayryeng')
tic
[rows, cols] = size(img);
[X, Y] = meshgrid(1:cols, 1:rows);
X = X(:);
Y = Y(:);
Mpq = sum((X - mean(X)).^p .* (Y - mean(Y)).^q .* img(:));
toc
disp('rayryeng with dot product');
tic
[rows, cols] = size(img);
[X, Y] = meshgrid(1:cols, 1:rows);
X = X(:);
Y = Y(:);
Mpq = ((X.' - mean(X)).^p )* ((Y - mean(Y)).^q .* img(:));
toc
disp('this solution - using bsxfun');
tic
sz = size( img ); %// assuming image is gray scale - 2D array
x = ( 1:sz(2) );
y = ( 1:sz(1) ).'; %'
x = x - mean(x);
y = y - mean(y);
Mpq = sum( reshape( bsxfun( @times, bsxfun( @times, img, x.^p ), y.^q ), [], 1 ) );
toc
Resulting with
Solution of rayryeng
Elapsed time is 0.009426 seconds.
rayryeng with dot product
Elapsed time is 0.008374 seconds.
this solution - using bsxfun
Elapsed time is 0.001404 seconds.
As you can see bsxfun
is significantly faster than meshgrid
-based solutions. Moreover, using dot-product instead of elem-wise product with sum
is faster.
f(x,y)
are simply your image intensities at each column location y
and each row location x
. If you want to calculate the pq moment for your image, you can do what Shai suggested which will probably be faster. However, if you want something more readable that doesn't use bsxfun , you can simply do this assuming your image is grayscale and stored in im
:
[rows, cols] = size(im);
im = double(im); %// For precision
[X, Y] = meshgrid(1:cols, 1:rows);
X = X(:);
Y = Y(:);
Mpq = sum((X - mean(X)).^p .* (Y - mean(Y)).^q .* im(:));
First we convert the image to double
to ensure that we get the best precision possible. Your image will probably be of type uint8
, and any values computed that exceed 255 will be clipped. You will probably get values beyond this and so casting to double
is recommended. We then use meshgrid
to generate a grid of spatial co-ordinates with the same size of the image, then unroll the co-ordinates to a single vector. This will make it easier to compute the moment. The last line of code finally computes our moment as per the equation. We also need to unroll the image in the same fashion so that the elements line up properly.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.