c中opencv中轮廓/对象的质心?

Aye*_*han 4 opencv image-processing visual-c++

是否有一些好的和更好的方法来找到opencv中的轮廓质心,而不使用内置函数?

Sam*_*Sam 6

虽然Sonaten的答案是完全正确的,但有一种简单的方法:使用专用的opencv函数:moment()

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

它不仅会返回质心,还会返回有关您的形状的更多统计信息.您可以发送轮廓或光栅形状(二进制图像),最适合您的需要.

编辑

示例(修改)来自"学习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); 
Run Code Online (Sandbox Code Playgroud)


Son*_*ten 2

您在当前代码段中得到的当然是边界框的质心。

“如果你有一堆点(二维向量),你应该能够通过平均这些点来获得质心:创建一个点将所有其他点的位置添加到其中,然后将该点的分量与累积位置除以总点数。” ——乔治·普罗芬扎提到

这确实是二维空间中任何给定物体的精确质心的正确方法。

在维基百科上,我们有一些寻找对象质心的通用形式。 http://en.wikipedia.org/wiki/Centroid

就我个人而言,我会问自己我需要从这个计划中得到什么。我想要一个彻底但性能要求较高的操作,还是想要做一些近似?我什至可以找到一个 OpenCV 函数来正确且有效地处理这个问题。

没有有效的示例,因此我在一个简单的 5 像素示例上以伪代码形式编写了一个完整的方法。

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)
Run Code Online (Sandbox Code Playgroud)

循环 x 像素

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)
Run Code Online (Sandbox Code Playgroud)

本质上,您拥有以下类型的矢量轮廓

vector<vector<point>>
Run Code Online (Sandbox Code Playgroud)

在 OpenCV 2.3 中。我相信你在早期版本中有类似的东西,你应该能够使用这个“双向量”的第一个索引来遍历图片上的每个斑点,并遍历内部向量中的每个像素。

这是轮廓函数文档的链接 http://opencv.itseez.com/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contours#cv.DrawContours

注意:您已将问题标记为 c++ Visual。我建议您在 OpenCV 2.3 中使用 c++ 语法而不是 c。使用 2.3 的第一个也是很好的理由是它更基于类,在本例中这意味着 Mat 类(而不是 IplImage)确实会泄漏内存。人们不必整天都编写销毁命令:)

我希望这可以帮助您解决问题。享受。