一、理论
获取opencv中轮廓的内部所有点,opencv有现成的函数判断点是否在轮廓内,但轮廓比较大的时候,直接调用pointPolygonTest速度会很慢。
我们可以通过扫描线的方式逐行对轮廓点进行遍历,获取穿过某一行的两个x值,这两个x值之间的点就都在轮廓内。
二、代码逻辑
低速版
cpp
static std::vector<cv::Point> getPointsInsideContour(const std::vector<cv::Point>& contour)
{
try {
std::vector<cv::Point> points;
if (contour.empty()) return points;
// 1. 获取包围盒
cv::Rect rect = cv::boundingRect(contour);
int yMin = rect.y;
int yMax = rect.y + rect.height;
//points.reserve(rect.width * rect.height);
// 2. 逐行扫描
for (int y = yMin; y < yMax; ++y)
{
for (int x = rect.tl().x; x < rect.br().x; x++)
{
Point p(x, y);
if (pointPolygonTest(contour, p, false) >= 0)
{
points.push_back(p);
}
}
}
return points;
}
catch (std::exception& ex)
{
throw std::runtime_error(ex.what());
}
}
高速版
1.同样获取轮廓的外接矩形
2.逐行对轮廓进行扫描
3.遍历轮廓点,判断轮廓的上一个点和下一个点是否存在穿过该行的行为
4.若存在,则保存起来对应的x值;对某行保存的x值进行排序,按照两两配对的方式获取这条填充线段
三、效果
debug版本下,轮廓点集1000W个点时,高速版是低速版的30多倍速度
获取源码请私信,可指导配置技术交流