【发布时间】:2016-10-30 20:35:56
【问题描述】:
我问了以下问题here 并得到了一个很好的解决方案,但发现它的性能太慢(640x480 图像需要 2-300 毫秒)。现在我想考虑如何优化它。
问题:
给定两个多边形(总是平行于 X 轴的梯形),我想通过某种方式计算它们匹配的程度。我的意思是,重叠区域是不够的,因为如果一个多边形有多余的区域,那么就需要以某种方式计算它。最理想的情况是,我想知道这两个多边形创建的区域有多少是常见的。例如,根据需要查看图片。
一个有效(但缓慢)的解决方案:
- 在空图像上绘制一个多边形 (cv::fillConvexPoly)
- 在空图像上绘制多边形二 (cv::fillConvexPoly)
- 执行按位并创建所有重叠像素的图像
- 计算所有非零像素 --> 重叠像素
- 反转第一张图像并用非反转的第二张重复 --> 过多的像素
- 反转第二张图像并使用未反转的第一张图像重复 --> 更多像素
- 将“重叠像素”与“过多像素”的总和相比较
如您所见,当前的解决方案是计算密集型的,因为它要对图像的每个像素进行大约 12 次评估/操作。我宁愿一个解决方案,计算这个区域,通过繁琐的构建和评估几个图像。
现有代码:
#define POLYGONSCALING 0.05
typedef std::array<cv::Point, 4> Polygon;
float PercentMatch( const Polygon& polygon,
const cv::Mat optimalmat )
{
//Create blank mats
cv::Mat polygonmat{ cv::Mat(optimalmat.rows, optimalmat.cols, CV_8UC1, cv::Scalar(0)) };
cv::Mat resultmat{ cv::Mat(optimalmat.rows, optimalmat.cols, CV_8UC1, cv::Scalar(0)) };
//Draw polygon
cv::Point cvpointarray[4];
for (int i =0; i < 4; i++ ) {
cvpointarray[i] = cv::Point(POLYGONSCALING * polygon[i].x, POLYGONSCALING *
polygon[i].y);
}
cv::fillConvexPoly( polygonmat, cvpointarray, 4, cv::Scalar(255) );
//Find overlapped pixels
cv::bitwise_and(polygonmat, optimalmat, resultmat);
int overlappedpixels { countNonZero(resultmat) };
//Find excessive pixels
cv::bitwise_not(optimalmat, resultmat);
cv::bitwise_and(polygonmat, resultmat, resultmat);
int excessivepixels { countNonZero(resultmat) };
cv::bitwise_not(polygonmat, resultmat);
cv::bitwise_and(optimalmat, resultmat, resultmat);
excessivepixels += countNonZero(resultmat);
return (100.0 * overlappedpixels) / (overlappedpixels + excessivepixels);
}
目前我设计的唯一性能改进是在函数外部绘制“最佳垫”,因此不会重绘(它与许多其他多边形相比),而且我添加了一个 POLYGONSCALING 来缩小多边形的大小和失去一些分辨率但获得一些性能。还是太慢了。
【问题讨论】:
-
Monte Carlo 也许?
-
或者你可以试着想出一个公式来计算重叠面积。您拥有所需的所有信息:每个梯形的点。
-
我会想出类似于 Mark Setchell 的答案。如果您可以在精度和处理速度之间进行权衡,您可以缩放梯形和图像以提高速度和/或如果梯形与图像相比较小,则使用边界框和子图像。根本没有讨论精度本身。也许 2D CSG 方法也可以,但我没有任何经验......
-
仔细看,重叠区域也是一个梯形。如果你知道每个梯形的点,那么你可以很容易地分解成重叠区域的面积方程。这可以与每个梯形的面积进行比较,以给出重叠百分比。您可以尝试的另一件事是减小图像的大小
标签: c++ opencv image-processing