寻找最大的轮廓C ++

时间:2017-09-13 01:39:18

标签: c++ opencv computer-vision detection contour

我目前正在尝试创建一个程序来查找收据的边缘,然后相应地裁剪它。我使用此代码执行此操作:

vector<vector<cv::Point> > contours;
vector<Vec4i> hierarchy;

findContours(edged, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
sort(contours.begin(), contours.end(), compareContourAreas);

vector<cv::Point> target;
for(int i = 0; i < contours.size(); i++){
    vector<cv::Point> c = contours[i];
    double p = arcLength(c, true);
    vector<cv::Point> approx;
    approxPolyDP(c, approx, 0.02*p, true);
    if (approx.size() == 4) {
        target = approx;
        break;
    }
}

此代码可以很好地找到轮廓,但不能正确过滤它们。例如,以下图片:

enter image description here enter image description here

左侧的图像代表所有轮廓,而右侧的图像代表目标。我想知道如何更改我的代码,以便我总是收到目标收据的边缘。

2 个答案:

答案 0 :(得分:0)

def sort(n):
    return n.size


image = cv2.imread("image.jpg",-1)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 210, 255, cv2.THRESH_BINARY)

img,contours,hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

ncontours = sorted(contours, key=sort,reverse=True )

rect = cv2.minAreaRect(ncontours[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image, [box], 0, (0,0,255),2)

result

答案 1 :(得分:0)

首先,您的问题是由于噪音,您根本找不到合适的轮廓。您应该对图像应用一些过滤,以使背景平滑和均匀。例如,尝试使用不同内核大小的cv::medianBlur() - 它会降低背景的清晰度。

其次,在找到图像上的所有轮廓后,您(可能)想要获得最大的轮廓。在这种情况下,您可以通过提供正确的std::sort参数,使用contours function向量矢量(我的意思是comp)。如果第一个轮廓大于第二个轮廓,则后者是一个应该采用2个轮廓并返回true的函数。要比较两个轮廓,您应该使用前面提到的函数cv::contourArea()

或者,您可以编写一个简单的函数:

int getMaxAreaContourId(vector <vector<cv::Point>> contours) {
    double maxArea = 0;
    int maxAreaContourId = -1;
    for (int j = 0; j < contours.size(); j++) {
        double newArea = cv::contourArea(contours.at(j));
        if (newArea > maxArea) {
            maxArea = newArea;
            maxAreaContourId = j;
        }
    return maxAreaContourId;
}

然后你会发现你的最大轮廓为contours.at(getMaxAreaContourId(contours))