OpenCV:能否从角落检测矩形?

7
我有一张照片,上面有个人拿着一张纸。我想检测出那张纸的矩形区域。

enter image description here

我已经尝试了来自OpenCV和各种SO答案和示例代码的不同教程,用于检测正方形/矩形,但问题在于它们都依赖于某种轮廓。
如果我按照squares.cpp示例进行操作,则会从轮廓中获得以下结果:

enter image description here

如您所见,手指是轮廓的一部分,因此算法无法找到正方形。
我也尝试使用 HoughLines() 方法,但结果与上述类似。

enter image description here

我可以可靠地检测出角落:

enter image description here

这张图片中还有其他角落,但我限制了找到的总角数不超过50个,并且纸张的角总是被找到。

是否有一种算法可以从图像中的多个角落中找到一个矩形?我似乎找不到现成的方法。


基本上,您需要获取轮廓,将它们提供给appoxPolyDP(),然后检查生成的approxCurve大小。如果是4,则表示您有一个四边形,那就是您的角落。之后,您可能需要重新排列角落的顺序,因为顺序不能保证。如果您需要更多帮助,请告诉我。 - MeetTitan
我尝试过这样做,但是手指的轮廓会超出纸张的边缘,而且appoxPolyDP函数无法识别它。 - Misha M
我不确定。你能循环遍历轮廓并检查是否存在90度的角吗? - MeetTitan
有趣的想法,但我不确定如何将角落对齐。 - Misha M
将手部从Photoshop中去除,然后自动化此过程。 - gen-y-s
使用cv::minAreaRect函数查找包围所有4个点的旋转矩形。对于透视失真的矩形角落,使用convexHull函数。 - Micka
1个回答

9
您可以应用形态学滤波器来关闭边缘图像中的间隙。然后,如果找到轮廓,您可以像下面显示的那样检测内部封闭轮廓。然后找到该轮廓的凸包以获取矩形。
封闭边缘:

closed

轮廓:

contour

凸包:

hull

在下面的代码中,我只是使用了一个任意的内核大小来进行形态学滤波,并使用面积比阈值过滤出感兴趣的轮廓。您可以使用自己的标准来替代这些内容。
代码:
Mat im = imread("Sh1Vp.png", 0); // the edge image
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(11, 11));
Mat morph;
morphologyEx(im, morph, CV_MOP_CLOSE, kernel);

int rectIdx = 0;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(morph, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
for (size_t idx = 0; idx < contours.size(); idx++)
{
    RotatedRect rect = minAreaRect(contours[idx]);
    double areaRatio = abs(contourArea(contours[idx])) / (rect.size.width * rect.size.height);
    if (areaRatio > .95)
    {
        rectIdx = idx;
        break;
    }
}
// get the convexhull of the contour
vector<Point> hull;
convexHull(contours[rectIdx], hull, false, true);

// visualization
Mat rgb;
cvtColor(im, rgb, CV_GRAY2BGR);
drawContours(rgb, contours, rectIdx, Scalar(0, 0, 255), 2);
for(size_t i = 0; i < hull.size(); i++)
{
    line(rgb, hull[i], hull[(i + 1)%hull.size()], Scalar(0, 255, 0), 2);
}

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