我正在尝试将LCD定位在一组图像中,但是目前在此过程中处于某个位置。这是感兴趣区域的二进制图像,如何从中提取内部矩形-或边界内角的坐标。
我尝试了以下方法,
使用Canny()
查找图像中的边缘,使用findContours()
查找轮廓。从轮廓列表中,我遇到了两个问题,
这是我的代码,
// threshold
Mat im1_thresh;
threshold(im1, im1_thresh, 100, 200, THRESH_BINARY);
// find edges
Mat im1_canny;
Canny(im1_thresh, im1_canny, 50, 100);
// find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(im1_canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// draw contours
RNG rng;
vector<Rect> boundRect(contours.size());
Mat im1_contours = Mat::zeros(im1_thresh.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++) {
// draw each contour in a different color
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(im1_contours, contours, i, color, 2, 8, hierarchy, 0, Point());
// draw bounding boxes around each contour in original image
boundRect[i] = boundingRect(Mat(contours[i]));
rectangle(im1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}
问题:如何从上面的二进制图像中定位内部矩形?
答案 0 :(得分:0)
为解决轮廓不连续的问题-我调整了阈值,直到轮廓平滑为止。有时模糊也有帮助。之后,选择最里面的轮廓。
我在上面的代码中使用了hierarchy
数组来选择相关的轮廓,并在原始图像上使用它创建一个边界框。层次结构数组是N * 4矩阵,其中N是轮廓数。对于每个轮廓,hierarchy
包含与相关轮廓有关的信息,例如[previous, next, child, parent]
。如果没有相关的轮廓,则可以看到值-1
。
这是相关图像的层次结构矩阵,
[-1,-1,1,-1]
[-1,-1,2,0]
[-1,-1,3,1]
[-1,-1,-1,2]
我对最后的轮廓感兴趣。它没有孩子,并且以2
为父。
这是我的实现,
Rect boundRect;
// loop through the contours/hierarchy
for (int i = 0; i<contours.size(); i++) {
// hierarchy is (previous, next, child, parent)
// look for innermost -- no child but a parent exists
if (hierarchy[i][2] == -1 && hierarchy[i][3] != -1) {
// draw contour
Scalar color = Scalar(255,0,0);
drawContours(im1_contours, contours, i, color);
// draw a bounding rectangle around original image
boundRect = boundingRect(Mat(contours[i]));
rectangle(im1, boundRect.tl(), boundRect.br(), color);
}
}
// subset the image
Mat im1_roi;
im1_roi = im1(boundRect);
答案 1 :(得分:0)
要找到最矩形的轮廓,可以运行minAreaRect
以适合旋转的矩形,然后将结果与原始轮廓进行比较。
每个区域的面积比例可能足够,具体取决于噪声等。
一旦选择了最矩形的轮廓,使用approxPoly
减少到4个点应该可以很好地近似屏幕矩形。
答案 2 :(得分:0)
从此图像中,我得到了10个以上的轮廓,只有外部矩形是一个完整的矩形。其余所有轮廓都是不相交的线,它们一起构成了内部矩形
您使用默认的Canny孔径= 3,尝试将其增大到5或7,它将检测到内部轮廓为一个,而不是多个小轮廓。试试这个:
int apertureSize = 5;
Canny(im1_thresh, im1_canny, 50, 100, apertureSize);
昨晚我碰到另一个问题,如果屏幕上有一个坏点,它也会出现在轮廓列表中。
检查每个轮廓的面积,以确保其大于最小可接受面积。您提供的图片尺寸为250x450,内部矩形尺寸为〜170x380。因此,您可以将minArea设置为170x380的80%(= 0.8 * 64600)。例如,在绘制之前将此检查添加到循环中。
float minArea = 0.8 * 64600;
if (boundRect[i].area() > minArea ){
rectangle(im1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}