Question

I want to get mass center of circle shape from binary image, but the output give more then one mass center. I'm using code from opencv web tutorial document about image moment and modified little bit. FYI, I'm using c++ API OpenCV.

And the output is:

AQ38S.jpg

I expect, the text output would give maybe 3 centroid from 3 contour, but reality is 7 contours (contours[0],...,contours[6]).

Which one the centroid? Or, which one the contour area of the circle shape?

Then I modified the code, remove some contours (because the real picture is very noise, and I just want to get some specific contours, circle shape, so I must remove the other contours, like line and character) using:

contours.erase()

I only want to get centroid from area contour between 100 till 500.

But, the output become strange..

xnDlZ.jpg

The centroids like fly to anywhere from their contours.
Then, still, there are 5 centroid from 5 contours (contours[0],...,contours[4]).

What must i do? I only want to get the centroid of circle shape (above the number 3). I'm really need your advice. Thank you so much! :D

*Sorry for my bad english..

Was it helpful?

Solution

What I would do:

  1. Find all the contours (and store the in a vector of point) (cv::findContours)
  2. Apply a custom particle filter. That is, a function that will tell you whether a contour is valid. To do that, you need to base your decision on morphological features such as

    • circularity
    • convexity
    • aspect ratio

Take a look at something like that to have visual examples: You can calculate the circularity from the area (cv::contourArea) and the perimeter (cv::arcLength) while convexity will involve computing the convex hull (cv::convexHull). This step should result in a new vector containing only valid (e.i. circular contours).

Your contourArea(contours[i], false) < 100 is a good start, but it will not tell you whether a contour is a circle.

After that, you can calculate a centre of gravity (and display it) of each element of your new vector. Does is make sense ?

Finally, I would not use contours.erase() for large vectors. I think iteratively erasing is a fairly heavy job for the CPU. Instead, I would store the good contours in a new preallocated vector. This is however just a performance detail.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top