# Why are the Hu moments of the middle shape different to the others?

I have calculated the Hu moments of three contours extracted from three images, which are simply rotated copies of each other. I was expecting the moments of all three contours to be similar, but the moments for the middle one are wildly different. If I do the same thing for three rectangles, the Hu moments are the same. Can anyone explain why the moments for my contours are so different?

Code for calculating the Hu moments with rectangles is as follows:

import cv2
import numpy as np
from matplotlib import pyplot as plt

def plot_image(pl, nImages, nRows, imageNumber, image, imageTitle):
plt.subplot(nImages, nRows, imageNumber)
plt.imshow(image, cmap='gray')
plt.title(imageTitle)
plt.xticks([])
plt.yticks([])

# Three rectangles at 45 degrees to each other
contours = [np.array([[[569, 108]], [[852, 391]], [[428, 815]], [[145, 532]]]),
np.array([[[440, 220]], [[840, 220]], [[840, 820]], [[440, 820]]]),
np.array([[[428, 391]], [[711, 108]], [[1135, 532]], [[852, 815]]])]

plotNumber = -1;
for contour in contours:
plotNumber = plotNumber + 1
contour_image = np.zeros((1280, 1280, 3), dtype=np.uint8)
contour_image.fill(255)
cv2.drawContours(contour_image, contours, -1, (192, 192, 192), 3)
cv2.drawContours(contour_image, [contour], -1, (64, 64, 64), 3)
moments = cv2.moments(contour)
HuM = cv2.HuMoments(moments)
title = "Contour {}".format(plotNumber)
print(title)
print("    Moments: '{}'".format(moments))
print("    Hu moments: '{}'".format(HuM))
plot_image(plt, 1, 3, plotNumber + 1, contour_image, title)

plt.show()


For the rectangles, this looks like this:

and calculates the following moments:

Contour 0

Hu moments: '[[ 1.80473837e-01] [ 4.79302812e-03] [ 4.91216000e-32] [ 2.69569756e-31] [-1.58512811e-62] [-1.79162613e-32] [ 2.66642577e-62]]'


Contour 1

Hu moments: '[[0.18055556] [0.00482253] [0.        ] [0.        ] [0.        ] [0.        ] [0.        ]]'


Contour 2

Hu moments: '[[ 1.80473837e-01] [ 4.79302812e-03] [ 1.58896395e-30] [ 3.42683065e-30] [ 6.79144186e-60] [ 1.07829350e-31] [-4.22127525e-60]]'


Replacing the rectangles with my contours looks like this:

and the calculated moments are:

Contour 0

Hu moments: '[[8.62421917e+01] [5.98422010e+02] [1.17817347e+05] [1.80083606e+04] [7.90111596e+08] [1.72868676e+05] [2.52571408e+08]]'


Contour 1

Hu moments: '[[ 1.71316578e-01] [ 1.60655638e-03] [ 5.04587028e-04] [ 7.51391253e-06] [-3.27447241e-10] [-3.00404360e-07] [-3.26860513e-10]]'


Contour 2

Hu moments: '[[8.66376920e+01] [6.08592878e+02] [1.19886409e+05] [1.71012017e+04] [7.20304630e+08] [1.37193728e+05] [2.84156598e+08]]'


I haven't included the contours themselves as they are quite long, but I can post them if required.

Any help would be appreciated.

edit retag close merge delete

Sort by » oldest newest most voted

Solved it myself! It turns out that the contours for two of the shapes were doubling back on themselves, effectively making a long, thin perimeter instead of a large squarish blob. The solution was to apply a bilateral filter to the grayscale image before thresholding, edge detection and contour extraction. This gives similar Hu moments for all the images.

more

Official site

GitHub

Wiki

Documentation