1
votes

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..

1
Hi, maybe you can make a very simple one-shape binary image and try you code over it. Also, this seems like an easy problem, but it is hard to help you without seeing your code... Do you want 1) to find shapes that are circles and 2) find there mass centre ?Quentin Geissmann
@QuentinGeissmann Thanks for your comment :D For the first picture, I'm using this code. For the second picture, I modified the code with put if ( contourArea(contours[i], false) < 100 || contourArea(contours[i], false) > 500) {contours.erase(contours.begin()+i); }.lulu
Honestly, yes, I want to find shapes that are circles and get the mass center. Do you have any advice? :Dlulu
Have you tried using the Hough transform for detecting circles?Zaphod
@Zaphod Thanks for your comment. :) I have and it isn't work, because this is hand drawing circle, so it just look-like-circle...lulu

1 Answers

0
votes

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.