Nodes/comfyui_cv/CV Shape Moments
ComfyUI Node

CV Shape Moments

Measures every contour with cv2.moments/cv2.HuMoments and surfaces the data the raw wrappers cannot: centroid, area, orientation angle and eccentricity (both from the second-order central moments), the major-axis segment, and the 7 log-scaled Hu invariants (translation/scale/rotation invariant shape signature - identical shapes give near-identical vectors regardless of pose). Hu is also blind to REFLECTION in everything but its 7th component, so the last three outputs recover what the invariance throws away: a canonical 0-360 orientation (resolved from the third-order moments, unlike 'angles' which is only defined mod 180), a signed handedness, and how much either can be trusted. All outputs are aligned with the input set, ready for 'CV Draw Points' (centroids), 'CV Draw Segments' (axes) and 'Inspect CV Data'. Zero contours is a valid result (empty arrays, count = 0), not an error.

By bmad4ever·Created 3 months ago·Updated 2 days ago· 0
CV Shape Moments
  • contours
  • centroids
  • areas
  • angles
  • eccentricities
  • axes
  • hu_moments
  • count
  • orientations
  • chirality
  • pose_confidence
Categoryimage/CV/contours

Inputs (1)

NameTypeDefaultDescription
contoursCV_CONTOURSFrom 'CV Find Contours'.

Outputs (10)

NameTypeDescription
centroidsNPARRAY(N,1,2) float32 center of mass per contour - plugs into 'CV Draw Points' / 'Draw Labels'.
areasNPARRAY(N,) float32 area in px^2 (the m00 moment).
anglesNPARRAY(N,) float32 orientation of the major axis in degrees, [-90, 90), measured from the +X axis with Y pointing DOWN (image coordinates). Meaningless for near-circular shapes (eccentricity ~ 0).
eccentricitiesNPARRAY(N,) float32 elongation in 0-1: 0 = perfect circle, -> 1 = a line. From the central-moment eigenvalues.
axesNPARRAY(N,4) float32 major-axis segments (x1, y1, x2, y2) through each centroid, 2 standard deviations long per side - plugs into 'CV Draw Segments'.
hu_momentsNPARRAY(N,7) float32 log-scaled Hu invariants: -sign(h)*log10(|h|) per component (the raw values span ~40 orders of magnitude). Compare shapes with 'CV Filter Contours By Shape' or a vector distance.
countINT
orientationsNPARRAY(N,) float32 canonical orientation in degrees, 0-360, from the +X axis with Y pointing DOWN. Unlike 'angles' (defined only mod 180) the head is told from the tail using the third-order moments, so a shape and its 180-degree rotation read differently. Always equals 'angles' or 'angles' + 180. MEANINGLESS when pose_confidence is ~0.
chiralityNPARRAY(N,) float32 signed handedness, from the 7th Hu invariant - the ONLY one that is not reflection-invariant (OpenCV: "invariants to the image scale, rotation, and reflection except the seventh one, whose sign is changed by reflection"; Hu 1962). h7 is also the one routinely DISCARDED in practice, because it is the smallest and noisiest of the seven - raw values here are ~1e-6 - so this output rescales it as sign(h7)*|h7|**0.25 to put it on a thresholdable scale. The SIGN flips when the shape is mirrored and survives any rotation or scale; the MAGNITUDE says how far to trust it: an 'F' glyph reads 0.020-0.048, a scalene triangle 0.0069, and a mirror-symmetric shape (square, circle, ellipse, isoceles triangle) reads below ~0.005, where the sign is only rasterization noise (OpenCV again: the invariance assumes "infinite image resolution"). It agrees in SIGN with hu_moments[:,6] - that column negates the sign but also takes log10 of a value far below 1, and the two flips cancel.
pose_confidenceNPARRAY(N,) float32 how well-defined 'orientations' is: the normalized third moment along the major axis. Measured 0.052 for a strongly asymmetric shape, 0.00057 for an ellipse and 0.0 for a square or circle - so test against ~0.005, not against 0. Below that the 0-360 orientation is a coin flip and any rotation measured from it is noise.