我试图找到轮廓的质心,但在用 C++(OpenCV 2.3.1)实现示例代码时遇到了麻烦。谁能帮我吗?
问问题
33077 次
4 回答
16
要找到轮廓的质心,可以使用矩量法。并且功能都是用OpenCV实现的。
查看这些矩函数(中心矩和空间矩)。
下面的代码取自 OpenCV 2.3 文档教程。完整代码在这里。
/// Find contours
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Get the moments
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
/// Get the mass centers:
vector<Point2f> mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
另请查看此 SOF,虽然它是在 Python 中,但它会很有用。它找到轮廓的所有参数。
于 2012-01-31T05:18:35.657 回答
6
如果你有轮廓区域的掩码,你可以找到质心位置如下:
cv::Point computeCentroid(const cv::Mat &mask) {
cv::Moments m = moments(mask, true);
cv::Point center(m.m10/m.m00, m.m01/m.m00);
return center;
}
当一个人有面具但没有轮廓时,这种方法很有用。cv::findContours(...)
在这种情况下,与使用然后找到质心相比,上述方法在计算上更有效。
于 2013-03-04T19:12:59.130 回答
1
给定轮廓点和Wikipedia中的公式,可以像这样有效地计算质心:
template <typename T>
cv::Point_<T> computeCentroid(const std::vector<cv::Point_<T> >& in) {
if (in.size() > 2) {
T doubleArea = 0;
cv::Point_<T> p(0,0);
cv::Point_<T> p0 = in->back();
for (const cv::Point_<T>& p1 : in) {//C++11
T a = p0.x * p1.y - p0.y * p1.x; //cross product, (signed) double area of triangle of vertices (origin,p0,p1)
p += (p0 + p1) * a;
doubleArea += a;
p0 = p1;
}
if (doubleArea != 0)
return p * (1 / (3 * doubleArea) ); //Operator / does not exist for cv::Point
}
///If we get here,
///All points lies on one line, you can compute a fallback value,
///e.g. the average of the input vertices
[...]
}
笔记:
- 此公式适用于以顺时针和逆时针顺序给出的顶点。
p
如果这些点具有整数坐标,则将返回值的和的类型调整为Point2f
或,并在返回语句中向分母添加Point2d
强制转换可能会很方便。float
double
于 2015-12-09T16:12:44.950 回答
0
如果您只需要近似质心,这里有几种简单的方法:
sumX = 0; sumY = 0;
size = array_points.size;
if(size > 0){
foreach(point in array_points){
sumX += point.x;
sumY += point.y;
}
centroid.x = sumX/size;
centroid.y = sumY/size;
}
或者借助 Opencv 的 boundingRect:
//pseudo-code:
Rect bRect = Imgproc.boundingRect(array_points);
centroid.x = bRect.x + (bRect.width / 2);
centroid.y = bRect.y + (bRect.height / 2);
于 2012-12-15T00:07:13.963 回答