Finding Largest Contours C++

a 夏天 提交于 2020-01-26 02:05:13

问题


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.


回答1:


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)




回答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.

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. The latter is a function that should take 2 contours and return true if the first contour is larger than the second one. To compare two contours you should use function cv::contourArea() as mentioned before.

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)).



来源:https://stackoverflow.com/questions/46187563/finding-largest-contours-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!