Algorithm to detect corners of paper sheet in photo

后端 未结 8 1478
暗喜
暗喜 2020-12-12 08:39

What is the best way to detect the corners of an invoice/receipt/sheet-of-paper in a photo? This is to be used for subsequent perspective correction, before OCR.

My

相关标签:
8条回答
  • 2020-12-12 09:37

    Here you have @Vanuan 's code using C++:

    cv::cvtColor(mat, mat, CV_BGR2GRAY);
    cv::GaussianBlur(mat, mat, cv::Size(3,3), 0);
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9,9));
    cv::Mat dilated;
    cv::dilate(mat, dilated, kernel);
    
    cv::Mat edges;
    cv::Canny(dilated, edges, 84, 3);
    
    std::vector<cv::Vec4i> lines;
    lines.clear();
    cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
    std::vector<cv::Vec4i>::iterator it = lines.begin();
    for(; it!=lines.end(); ++it) {
        cv::Vec4i l = *it;
        cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
    }
    std::vector< std::vector<cv::Point> > contours;
    cv::findContours(edges, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS);
    std::vector< std::vector<cv::Point> > contoursCleaned;
    for (int i=0; i < contours.size(); i++) {
        if (cv::arcLength(contours[i], false) > 100)
            contoursCleaned.push_back(contours[i]);
    }
    std::vector<std::vector<cv::Point> > contoursArea;
    
    for (int i=0; i < contoursCleaned.size(); i++) {
        if (cv::contourArea(contoursCleaned[i]) > 10000){
            contoursArea.push_back(contoursCleaned[i]);
        }
    }
    std::vector<std::vector<cv::Point> > contoursDraw (contoursCleaned.size());
    for (int i=0; i < contoursArea.size(); i++){
        cv::approxPolyDP(Mat(contoursArea[i]), contoursDraw[i], 40, true);
    }
    Mat drawing = Mat::zeros( mat.size(), CV_8UC3 );
    cv::drawContours(drawing, contoursDraw, -1, cv::Scalar(0,255,0),1);
    
    0 讨论(0)
  • 2020-12-12 09:45

    A student group at my university recently demonstrated an iPhone app (and python OpenCV app) that they'd written to do exactly this. As I remember, the steps were something like this:

    • Median filter to completely remove the text on the paper (this was handwritten text on white paper with fairly good lighting and may not work with printed text, it worked very well). The reason was that it makes the corner detection much easier.
    • Hough Transform for lines
    • Find the peaks in the Hough Transform accumulator space and draw each line across the entire image.
    • Analyse the lines and remove any that are very close to each other and are at a similar angle (cluster the lines into one). This is necessary because the Hough Transform isn't perfect as it's working in a discrete sample space.
    • Find pairs of lines that are roughly parallel and that intersect other pairs to see which lines form quads.

    This seemed to work fairly well and they were able to take a photo of a piece of paper or book, perform the corner detection and then map the document in the image onto a flat plane in almost realtime (there was a single OpenCV function to perform the mapping). There was no OCR when I saw it working.

    0 讨论(0)
提交回复
热议问题