Contour / object centroid in opencv in c?

Is there any good and better way to find the centroid contour in opencv without using the built-in functions?

+4
source share
3 answers

While Sonaten's answer is perfectly correct, there is an easy way to do this: use the opencv function: moments () for this

http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=moments#moments

It returns not only the center of gravity, but also some statistics about your figure. And you can send it an outline or bitmap shape (binary image), whatever is best for you.

EDIT

example (modified) from "Learning OpenCV", gary bradsky

CvMoments moments; double M00, M01, M10; cvMoments(contour,&moments); M00 = cvGetSpatialMoment(&moments,0,0); M10 = cvGetSpatialMoment(&moments,1,0); M01 = cvGetSpatialMoment(&moments,0,1); centers[i].x = (int)(M10/M00); centers[i].y = (int)(M01/M00); 
+6
source

What you get in your current code snippet is, of course, the centroid of your bounding box.

"If you have a bunch of points (2nd vector), you can get a centroid by averaging these points: create a point to add all the positions of other points and separate the components of this point using the accumulated positions for the total number of points." - George Profenzi mentions

This is really the right approach for the exact center of gravity of any given object in two-dimensional space.

On Wikipedia, we have some common forms for finding the centroid of an object. http://en.wikipedia.org/wiki/Centroid

Personally, I asked myself what I need from this program. Do I wish for a thorough but high-performance work, or do I want to make some approximations? I could even find an OpenCV function that handles this correctly and efficiently.

You don't have a working example, so I write this in pseudo-code on a simple 5-pixel example using a thorough method.

 x_centroid = (pixel1_x + pixel2_x + pixel3_x + pixel4_x +pixel5_x)/5 y_centroid = (pixel1_y + pixel2_y + pixel3_y + pixel4_y +pixel5_y)/5 centroidPoint(x_centroid, y_centroid) 

Looped for x pixels

 Loop j times *sample (for (int i=0, i < j, i++))* { x_centroid = pixel[j]_x + x_centroid y_centroid = pixel[j]_x + x_centroid } x_centroid = x_centroid/j y_centroid = y_centroid/j centroidPoint(x_centroid, y_centroid) 

Essentially, you have type vector outlines

 vector<vector<point>> 

in OpenCV 2.3. I believe that you have something similar in earlier versions, and you must go through each frame in your picture with the first index of this β€œdouble vector” and go through each pixel in the inner vector.

Here is a link to the outline function documentation http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contours#cv.DrawContours

note: you marked your question as visual C ++. I would suggest using C ++ syntax in OpenCV 2.3 instead of c. The first and good reason for using 2.3 is that it is more based on the class, which in this case means that the Mat class (instead of IplImage) is leaking memory. No need to write destruction commands all live day :)

Hope this clarifies your issue. Enjoy it.

+2
source

I used the superior Joseph O'Rourke polyhedral centroid algorithm for success.

See http://maven.smith.edu/~orourke/Code/centroid.c

Essentially:

  • For each contour point, find the area of ​​the triangle from the current polygon xy to the following two points of the polygon xy, for example: Math.Abs ​​(((X1 - X0) * (Y2 - Y0) - (X2 - X0)) * (Y1 - Y0 )) / 2)
  • Add this area of ​​the triangle to the TriAreas list.
  • Sum the area of ​​the triangle and save in SumT
  • Find the centroid CTx and CTy from this current triangle: CTx = (X0 + X1 + X2) / 3 and CTy = (Y0 + Y1 + Y2) / 3;
  • Save these 2 centroid values ​​in the other two CTxs CTys lists.
  • Finally, after doing this with all the contour points, find the contours of the centroid x and y, using 2 triangles x and y in list 5, which is the weighted sum of the signed areas of the triangle, weighted by the centroid of each triangle:

      for (Int32 Index = 0; Index < CTxs.Count; Index++) { CentroidPointRet.X += CTxs[Index] * (TriAreas[Index] / SumT); } // now find centroid Y value for (Int32 Index = 0; Index < CTys.Count; Index++) { CentroidPointRet.Y += CTys[Index] * (TriAreas[Index] / SumT); } 
+1
source

Source: https://habr.com/ru/post/1381381/


All Articles