Ask Your Question
2

Getting picture contours

asked 2017-08-02 10:47:46 -0600

Ahmed gravatar image

updated 2020-10-28 02:37:25 -0600

I'm trying to extract the following image, and do perspective correction but its not working as expected.

image description here is my full code

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;
double angle(cv::Point pt1, cv::Point pt2, cv::Point pt0) {
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

void find_squares(Mat& image, vector<vector<Point> >& squares)
{
    // blur will enhance edge detection
    Mat blurred(image);
    Mat dst;
    medianBlur(image, dst, 9);

    Mat gray0(dst.size(), CV_8U), gray;
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    for (int c = 0; c < 3; c++)
    {
        int ch[] = { c, 0 };
        mixChannels(&dst, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        const int threshold_level = 2;
        for (int l = 0; l < threshold_level; l++)
        {
            // Use Canny instead of zero threshold level!
            // Canny helps to catch squares with gradient shading
            if (l == 0)
            {
                Canny(gray0, gray, 10, 20, 3); // 

                                               // Dilate helps to remove potential holes between edge segments
                dilate(gray, gray, Mat(), Point(-1, -1));
            }
            else
            {
                gray = gray0 >= (l + 1) * 255 / threshold_level;
            }

            // Find contours and store them in a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            // Test contours
            vector<Point> approx;
            for (size_t i = 0; i < contours.size(); i++)
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if (approx.size() == 4 &&
                    fabs(contourArea(Mat(approx))) > 1000 &&
                    isContourConvex(Mat(approx)))
                {
                    double maxCosine = 0;

                    for (int j = 2; j < 5; j++)
                    {
                        double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
                        maxCosine = MAX(maxCosine, cosine);
                    }

                    if (maxCosine < 0.3)
                        squares.push_back(approx);
                }
            }
        }
    }
}


cv::Mat debugSquares(std::vector<std::vector<cv::Point> > squares, cv::Mat image)
{
    for (int i = 0; i< squares.size(); i++) {
        // draw contour
        cv::drawContours(image, squares, i, cv::Scalar(255, 0, 0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());

        // draw bounding rect
        cv::Rect rect = boundingRect(cv::Mat(squares[i]));
        cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0, 255, 0), 2, 8, 0);

        // draw rotated rect
        cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));
        cv::Point2f rect_points[4];
        minRect.points(rect_points);
        for (int j = 0; j < 4; j++) {
            cv::line(image, rect_points[j], rect_points[(j + 1) % 4], cv::Scalar(0, 0, 255), 1, 8); // blue
        }
    }

    return image;
}


static std::vector<cv::Point> extremePoints(std::vector<cv::Point>pts)
{
    int  xmin = 0, ymin = 0, xmax = -1, ymax = -1, i;
    Point ptxmin, ptymin, ptxmax, ptymax;

    Point pt = pts[0];

    ptxmin = ptymin = ptxmax = ptymax = pt;
    xmin = xmax = pt.x;
    ymin = ymax = pt.y;

    for (size_t i = 1; i < pts.size(); i++)
    {
        pt = pts[i];

        if (xmin > pt.x)
        {
            xmin ...
(more)
edit retag flag offensive close merge delete

Comments

are you trying to achieve proposed solution in http://answers.opencv.org/question/17....

sturkmen gravatar imagesturkmen ( 2017-08-02 10:56:14 -0600 )edit

yes I'm trying to achieve it

Ahmed gravatar imageAhmed ( 2017-08-02 10:59:56 -0600 )edit

OK. it seems you did not interested with my answer. It was worth trying.

to answer this question i say there is plenty of samples to achieve this in this forum and stackoverlow. please delete this answer and do some search.

sturkmen gravatar imagesturkmen ( 2017-08-02 11:07:22 -0600 )edit

can you give me some keypoints to search for ?

Ahmed gravatar imageAhmed ( 2017-08-02 11:17:15 -0600 )edit

I insist on trying the following demo program https://github.com/takmin/OpenCV-Mark...

sturkmen gravatar imagesturkmen ( 2017-08-02 11:23:36 -0600 )edit

later if you still want to find contours i will help you

sturkmen gravatar imagesturkmen ( 2017-08-02 11:24:28 -0600 )edit

I'm interested to find contours because I got some results

Ahmed gravatar imageAhmed ( 2017-08-02 12:06:35 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2017-08-02 14:18:53 -0600

updated 2017-08-14 08:08:30 -0600

you can find my trial C++ source code on github for getting some result images below

image description ------------> image description


image description ----------------> image description

used referencess:

  1. http://study.marearts.com/2015/03/ima...
  2. http://web.archive.org/web/2015031701...
edit flag offensive delete link more

Comments

Thanks so much. but it needs alot of work so that it can be adapted to general paper detection

Ahmed gravatar imageAhmed ( 2017-08-02 15:39:33 -0600 )edit

http://imgur.com/a/GQhIX

for example an image like this, it won't work :(

Ahmed gravatar imageAhmed ( 2017-08-02 15:44:33 -0600 )edit
sturkmen gravatar imagesturkmen ( 2017-08-02 15:45:17 -0600 )edit

Thanks I managed to do it. How would I unwarp the image to be a rectuangluar quad ? should I make a new question

Ahmed gravatar imageAhmed ( 2017-08-02 16:33:20 -0600 )edit

see my answer in this post. it has perspective transformation

lines

    RotatedRect minRect = minAreaRect( Mat(contours[i]) );
    .
    .
    .
    warpPerspective( thresh, quad, transmtx, img.size());

try to adopt it

sturkmen gravatar imagesturkmen ( 2017-08-02 16:52:19 -0600 )edit

I tried to adop it, but stil very hard to get it done. If you have some time, later, I would be happy if you do it

Ahmed gravatar imageAhmed ( 2017-08-02 17:57:41 -0600 )edit
1

post your code somewhere let me do it

sturkmen gravatar imagesturkmen ( 2017-08-02 18:12:14 -0600 )edit

https://pastebin.com/0wYM2666 Here is the code, many thanks

Ahmed gravatar imageAhmed ( 2017-08-03 02:16:17 -0600 )edit

I'm waiting your help please

Ahmed gravatar imageAhmed ( 2017-08-03 07:24:02 -0600 )edit

i edited your question. see the code

sturkmen gravatar imagesturkmen ( 2017-08-03 08:16:06 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-08-02 10:47:46 -0600

Seen: 6,069 times

Last updated: Aug 14 '17