简体   繁体   English

查找最大轮廓C ++

[英]Finding Largest Contours C++

I am currently trying to create a program that finds the edges of a receipt and then crops it accordingly. 我目前正在尝试创建一个程序,该程序可以找到收据的边缘,然后进行相应的裁剪。 I used this code to do so: 我使用以下代码来做到这一点:

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;
    }
}

This code finds the contours just fine, but doesn't filter them correctly. 这段代码找到的轮廓很好,但是没有正确过滤它们。 For example, the following images: 例如,以下图像:

在此处输入图片说明 在此处输入图片说明

The image on the left represents all the contours while the image to the right just represent the target. 左侧的图像代表所有轮廓,而右侧的图像仅代表目标。 I'm wondering how I can change my code so that I always receive the edges of the receipt for target. 我想知道如何更改代码,以便始终获得目标收据的边缘。

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)

结果

First, your problem is that you are not finding the right contour at all because of a noise. 首先,您的问题是由于噪音而根本找不到正确的轮廓。 You should apply some filtering to your image in order to make background smooth and uniform. 您应该对图像进行一些过滤,以使背景平滑和均匀。 For example, try cv::medianBlur() with different kernel sizes - it will decrease the sharpness of the background. 例如,尝试使用具有不同内核大小的cv::medianBlur() -它会降低背景的清晰度。

Second, after you find all contours on the image, you will (probably) want to get the largest one. 其次,在图像上找到所有轮廓后,您(可能)会想要获得最大的轮廓。 In this case you can use std::sort function your vector-of-vectors (I mean contours ) by providing correct comp argument. 在这种情况下,您可以通过提供正确的comp参数,将std::sort 函数用作向量矢量(我的意思是contours )。 The latter is a function that should take 2 contours and return true if the first contour is larger than the second one. 后者是一个函数,该函数应采用2个轮廓,如果第一个轮廓大于第二个轮廓,则返回true To compare two contours you should use function cv::contourArea() as mentioned before. 要比较两个轮廓,应使用函数cv::contourArea() ,如前所述。

Or, you can write a simple function like that: 或者,您可以编写一个简单的函数,例如:

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;
        } // End if
    } // End for
    return maxAreaContourId;
} // End function

And then you find your largest contour as contours.at(getMaxAreaContourId(contours)) . 然后,您找到最大的轮廓为contours.at(getMaxAreaContourId(contours))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM