OpenCV 2 质心

发布于 2025-01-01 02:06:46 字数 61 浏览 0 评论 0原文

我试图找到轮廓的质心,但在 C++ (OpenCV 2.3.1) 中实现示例代码时遇到问题。有人可以帮我吗?

I am trying to find the centroid of a contour but am having trouble implementing the example code in C++ (OpenCV 2.3.1). Can anyone help me out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对岸观火 2025-01-08 02:06:46

要找到轮廓的质心,可以使用矩量法。并且功能都是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的,但是还是很有用的。它找到轮廓的所有参数。

To find the centroid of a contour, you can use the method of moments. And functions are implemented OpenCV.

Check out these moments function (central and spatial moments).

Below code is taken from OpenCV 2.3 docs tutorial. Full code here.


/// 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 ); } 

Also check out this SOF, although it is in Python, it would be useful. It finds all parameters of a contour.

星星的軌跡 2025-01-08 02:06:46

如果您有轮廓区域的掩模,则可以按如下方式找到质心位置:

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(...) 然后查找质心相比,上述方法在计算上更加高效。

这是来源

If you have the mask of the contour area, you can find the centroid location as follows:

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;
}

This approach is useful when one has the mask but not the contour. In that case the above method is computationally more efficient vs. using cv::findContours(...) and then finding mass center.

Here's the source

維他命╮ 2025-01-08 02:06:46

给定轮廓点和 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 的类型和返回值的类型调整为 Point2fPoint2d 可能会很方便,
    并在 return 语句中将分母添加为 floatdouble

Given the contour points, and the formula from Wikipedia, the centroid can be efficiently computed like this:

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
    [...]
}

Note:

  • This formula works with vertices given both in clockwise and
    counterclockwise order.
  • If the points have integer coordinates, it
    might be convenient to adapt the type of p and of the return value to Point2f or Point2d,
    and to add a cast to float or double to the denominator in the return statement.
老娘不死你永远是小三 2025-01-08 02:06:46

如果您需要的只是质心的近似值,这里有一些简单的方法可以实现:

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);

If all you need is an approximation of the centroid here are a couple of simple ways to do it:

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;
}

Or with the help of Opencv's boundingRect:

//pseudo-code:

Rect bRect = Imgproc.boundingRect(array_points);

centroid.x = bRect.x + (bRect.width / 2);
centroid.y = bRect.y + (bRect.height / 2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文