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);
}