简体   繁体   中英

How do I calculate the central moment in an image?

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 , 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM