Finding blob centers with keypoints or centroids?

The following pseudocode code works fine in reality, but I have a question concerning the appropriateness with what I am trying to do. I detect a few simple blobs ovoid to circular in nature, in a binary image. I am trying to find the blob centers:

Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params); 
...image aquisition (ImageRaw)
...convert to binary (bin_image) 
	detector->detect(bin_image, binKeypoints);
	drawKeypoints(bin_image, binKeypoints, binimg_with_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

The keypoints returned: do they contain the center coordinates of the blobs detected or should I calculate the centroid of the blob using using an algorithm, a bounding box middle or even by applying a moments function? Where do I go from here to find center coords?

the keypoint center is already derived from the contour moments:

Hi thanks for the recommended solution. Would a “geometric solution” be acceptable as well as simpler? I basically find the leftmost, rightmost, lower-most, higher-most pixel coordinates of the blob in the image plane and calculate the rectangular center from this virtual bounding box. Assuming a relatively symmetrical blob which I am using. How can I find the coordinates marked with “?”
Pseudo:

Main
{
…
// per found blob
double Pixel_leftmost = ?
double Pixel_rightmost = ?
double Pixel_upmost = ?
double Pixel downmost = ?

double Width_blob = Pixel_rightmost - Pixel_leftmost
double Height_blob = Pixel_downmost - Pixel_upmost // avoid neg quant

double Ctr_x = Width_blob/2
double Ctr_y = Height_blob/2
…
}

this is neither a recommendation, nor a solution.
just stating, how it works “under the hood”.

there is indeed a difference between the

  • “center of gravity” (as calculated from moments())
  • and the “geometric center” (the center of the bounding box, what your “pseudocode” above is trying to calculate)

what exactly do you require here (and why) ?

what exactly do you require here (and why) ?

I’ll have to do some reading about center of gravity versus geometric center and repost --honestly I don’t know the diff. I do know I want to avoid contours and to work with 1-2 round binary blobs that are moving. The algorithm should be light weight and with as few OpenCV fx calls as possible. I am presently using binary keypoints.x etc. as center image points but this is probably not right though close.

I’ve done a lot of reading on the two approaches above. Turns out it appears that the
keypoints already contain centroid coordinates that correlate with image points :

bin_with_keypoints[i].pt.x;
bin_with_keypoints[i].pt.y;

// or equivalent

bin_with_keypoints[i].pt[0];
bin_with_keypoints[i].pt[1];

That’s fine. But I also want to find the blob centers using “moments” to compare as well. However I’m kneecapped immediately with an exception in the the first line of Moments m.

...code to aquire a frame (greyscale) and convert to binary. Tested = ok.
Moments m = moments(matBinImage, true);  // exception line

Code snippet:

Moments m = moments(matBinImage, true);  // exception line
Point p(m.m10/m.m00, m.m01/m.m00);
//centroid coordinates
cout<<Mat(p) << std::endl;

the keypoint positions are already calculated using moments, no reason to do it again.

and the exception is ?

please also be aware, that you only can calculate the moments of a single contour

Unhandled exception at 0x00007FFC290BA388 in Testver7.exe: Microsoft C++ exception: cv::Exception at memory location 0x0000002EB4BFEB60

please also be aware, that you only can calculate the moments of a single contour

I plan on using a single blob. Can this be considered as a single contour?

can you show your “matBinImage” ?
(and some code around that ?)

sure.

cv::Mat matBinaryImg;
threshold(imageUndistorted, matBinaryImg, 60, 255, THRESH_BINARY);
imshow("Binary Image:", matBinaryImg);
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);  
			// Detect blobs
			detector->detect(matBinaryImg, binKeypoints);
			drawKeypoints(matBinaryImg, binKeypoints, bin_with_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);