在OpenCV中寻找多边形边界内的平均颜色

8

背景

我正在尝试使用OpenCV创建一个实用程序,该实用程序将返回给定多边形内的平均像素颜色。该多边形将由4个点定义,但不一定是矩形/正方形。例如,可以预期以下结构:

     A__________B    A_______B
    /          /     \       \
   /          /       \       \
 D/__________/C       D\_______\C

在OpenCV中,给定一个cv::Mat图像和由点(A,B,C,D)定义的多边形。我知道点A、B、C和D,但我想计算多边形内的平均像素颜色。我希望从OpenCV社区中获得一些关于如何最有效地完成此任务的建议。


研究完成

在StackOverflow上的另一篇 帖子 建议使用 drawContours 函数绘制轮廓,然后取包围轮廓的边界矩形的 平均值。我显然必须修改平均值计算,以便它使用由 fillPoly 函数绘制的多边形。

建议/关注点是非常感激的!


还要注意,在你提供的答案中,平均值不是在边界框上计算的,而是在多边形掩码上计算的。边界框仅用于聚焦多边形真正存在的掩码部分(这可能是一个很好的优化)。 - Miki
1个回答

14

您可以简单地使用平均值函数和一个掩模(mask),其中掩模是填充的多边形。

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;

int main()
{
    // Create a black image with a gray rectangle on top left
    Mat1b img(300, 300, uchar(0));
    rectangle(img, Rect(0, 0, 100, 100), Scalar(100), CV_FILLED);

    // Define a polygon
    Point pts[1][4];
    pts[0][0] = Point(20, 20);
    pts[0][1] = Point(40, 100);
    pts[0][2] = Point(200, 60);
    pts[0][3] = Point(150, 30);

    const Point* points[1] = {pts[0]};
    int npoints = 4;

    // Create the mask with the polygon
    Mat1b mask(img.rows, img.cols, uchar(0));
    fillPoly(mask, points, &npoints, 1, Scalar(255));

    // Compute the mean with the computed mask
    Scalar average = mean(img, mask);

    std::cout << average << std::endl;

    return 0;
}

所以如果我有多个多边形,我想一个接一个地使用掩码,那么我将需要将“pts”变量填充到numPolygons,并迭代每个多边形并为该多边形创建掩码。正确吗? - Jonathan
1
理论上是可以的,但是我认为在fillPoly中无法指定绘制第n个多边形。所以我认为最好一次只填充pts中的一个多边形,并将该单个多边形绘制到fillPoly中。 - Miki
太好了。谢谢! - Jonathan
这种方法不是非常低效吗? 对多边形进行着色并不是一项微不足道的任务。此外,如果Mat非常大而多边形是一个小矩形,通过索引访问矩形中的所有值并计算平均值不是更有效吗? - David Sackstein
@DavidSackstein 1) 这不是一个矩形,而是一个多边形。因此,您需要找到哪个点在多边形内部的方法。cv::fillPolygon是一个很好的选择,因为它创建了一个可以提供给cv::mean的掩码。2) 这个问题与性能无关。3) 如果您谈论性能,您需要对您的用例进行分析。这种方法可能不是最好的,但它几乎不会成为您应用程序的瓶颈。4) 您可以在较小的roi上工作,但这取决于您的用例。5) 如果您有更好的答案,可以发布您的答案 ;) - Miki
@Miki 我认为你关于将这种技术应用于多边形的边界框而不是应用于整个图像的评论解决了我的担忧。 - David Sackstein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接