OpenCV:是否可以从角落检测矩形?
OpenCV: Is it possible to detect rectangle from corners?
我有一张人手拿着 sheet 纸的照片。我想检测那张 sheet 纸的矩形。
我尝试按照 OpenCV 的不同教程以及各种 SO 答案和示例代码来检测正方形/矩形,但问题是它们都依赖于某种轮廓。
如果我按照 squares.cpp
的例子,我从等高线得到以下结果:
如你所见,手指是轮廓的一部分,所以算法没有找到正方形。
我也尝试过使用 HoughLines()
方法,但我得到的结果与上面类似:
我可以可靠地检测到角点:
图像中还有其他角,但我将发现的角总数限制在 < 50 个以内,并且 sheet 纸张的角 总是 找到。
是否有某种算法可以从图像的多个角中找到一个矩形?我似乎找不到现有的方法。
您可以应用形态过滤器来缩小边缘图像中的间隙。然后,如果找到轮廓,则可以检测到内部闭合轮廓,如下所示。然后求这个轮廓的凸包得到矩形
闭合边:
轮廓:
凸包:
在下面的代码中,我刚刚使用任意内核大小进行形态学过滤,并使用面积比阈值过滤掉感兴趣的轮廓。您可以使用自己的标准代替那些标准。
代码
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);
}
我有一张人手拿着 sheet 纸的照片。我想检测那张 sheet 纸的矩形。
我尝试按照 OpenCV 的不同教程以及各种 SO 答案和示例代码来检测正方形/矩形,但问题是它们都依赖于某种轮廓。
如果我按照 squares.cpp
的例子,我从等高线得到以下结果:
如你所见,手指是轮廓的一部分,所以算法没有找到正方形。
我也尝试过使用 HoughLines()
方法,但我得到的结果与上面类似:
我可以可靠地检测到角点:
图像中还有其他角,但我将发现的角总数限制在 < 50 个以内,并且 sheet 纸张的角 总是 找到。
是否有某种算法可以从图像的多个角中找到一个矩形?我似乎找不到现有的方法。
您可以应用形态过滤器来缩小边缘图像中的间隙。然后,如果找到轮廓,则可以检测到内部闭合轮廓,如下所示。然后求这个轮廓的凸包得到矩形
闭合边:
轮廓:
凸包:
在下面的代码中,我刚刚使用任意内核大小进行形态学过滤,并使用面积比阈值过滤掉感兴趣的轮廓。您可以使用自己的标准代替那些标准。
代码
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);
}