Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

What do you mean for not really working ? cv::moments works with ...raster image (single-channel, 8-bit or floating-point 2D array) or an array (1×N or N×1 ) of 2D points (Point or Point2f ) and returns moments

You should to be sure of your points values correctness even if ...the moments computed for a contour are slightly different from the moments computed for the same rasterized contour

BTW, You can extract just the image from the i-th label and use it to calculate moment...as below

Mat src,contMat, binImg, lblImg,objImg;
src = imread("../img/test.jpg");
cvtColor(src, contMat, CV_BGR2GRAY);
cv::threshold(contMat, binImg, 50, 255, THRESH_BINARY);

int numLabels=connectedComponents(binImg, lblImg, 8);

// select one-by-one ALL labelled objects using its label values
for (int lbl = 0; lbl < numLabels; lbl++) {
    // select the image part relative to lbl
    objImg = (lblImg == lbl);              
    Moments m = cv::moments(objImg, true); // get moments as world coordinates
    // get and draw the center
    // remember m.m00 could be 0 if object has self-intersections
    if (m.m00 != 0) {
        Point center;
        center.x = m.m10 / m.m00;
        center.y = m.m01 / m.m00;
        cv::circle(contMat, center, 3, Scalar(0, 255, 0), -1);
    }
}

As alternative, you can do the same using your points vector

//get the label value related to current vector points
int lbl = lblImg.at<uchar>(points[0]);
// select the image part relative to lbl as above
objImg = (lblImg == lbl);
...same as above

3rd way optmize memory usage using your points to create a ROI around the i-th object

int lbl = lblImg.at<uchar>(points[0]); // get the label value
Rect objRect = boundingRect(points);
Mat objROI = lblImg(objRect);          // get a ROI for lbl-th object
objROI = (objROI == lbl);              // select pixel from lbl-th label only
Moments m = cv::moments(objImg, true); // get moments as ROI coordinates
if (m.m00 != 0) {
    Point center;
    center.x = m.m10 / m.m00;
    center.y = m.m01 / m.m00;
    // back to world coordinates
    center += objRect.tl;
    cv::circle(contMat, center, 3, Scalar(0, 255, 0), -1);
}