Robust edge detection OpenCV

asked 2014-04-21 00:20:46 -0600

Luek gravatar image

updated 2020-11-06 05:29:31 -0600

I have been using this method to find a card and crop it out of the image:

void findCardAndCrop(Mat& bw,Mat& outerBox)
{
    // Remove noise
    GaussianBlur(bw, bw, cv::Size(11,11), 0);

    adaptiveThreshold(bw, outerBox, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 101, 16);
    bitwise_not(outerBox, outerBox);
    Mat kernel = (Mat_<uchar>(3,3) << 0,1,0,1,1,1,0,1,0);
    dilate(outerBox, outerBox, kernel);

    //int count=0;
    int max=-1;
    cv::Point maxPt;

    for(int y=0;y<outerBox.size().height;y++)
    {
        uchar *row = outerBox.ptr(y);
        for(int x=0;x<outerBox.size().width;x++)
        {
            if(row[x]>=128)
            {
                int area = floodFill(outerBox, cv::Point(x,y), 64);

                if(area>max)
                {
                    maxPt = cv::Point(x,y);
                    max = area;
                }
            }
        }
    }
    floodFill(outerBox, maxPt, CV_RGB(255,255,255));

    for(int y=0;y<outerBox.size().height;y++)
    {
        uchar *row = outerBox.ptr(y);
        for(int x=0;x<outerBox.size().width;x++)
        {
            if(row[x]==64 && x!=maxPt.x && y!=maxPt.y)
            {
                int area = floodFill(outerBox, cv::Point(x,y), CV_RGB(0,0,0));
            }
        }
    }

    erode(outerBox, outerBox, kernel);

    vector<Vec2f> lines;
    HoughLines(outerBox, lines, 1, CV_PI/180, 1200);
    mergeRelatedLines(&lines, outerBox);

    for(int i=0;i<lines.size();i++)
    {
        drawLine(lines[i], outerBox, CV_RGB(0,0,128));
    }

    Vec2f topEdge = Vec2f(1000,1000);   //double topYIntercept=100000;//, topXIntercept=0;
    Vec2f bottomEdge = Vec2f(-1000,-1000);      //double bottomYIntercept=0;//, bottomXIntercept=0;
    Vec2f leftEdge = Vec2f(1000,1000);  double leftXIntercept=100000;//, leftYIntercept=0;
    Vec2f rightEdge = Vec2f(-1000,-1000);       double rightXIntercept=0;//, rightYIntercept=0;
    for(int i=0;i<lines.size();i++)
    {
        Vec2f current = lines[i];

        float p=current[0];
        float theta=current[1];

        if(p==0 && theta==-100)
            continue;

        double xIntercept, yIntercept;
        xIntercept = p/cos(theta);
        yIntercept = p/(cos(theta)*sin(theta));

        if(theta>CV_PI*80/180 && theta<CV_PI*100/180)
        {
            if(p<topEdge[0])
                topEdge = current;

            if(p>bottomEdge[0])
                bottomEdge = current;

            //printf("X: %f, Y: %f\n", xIntercept, yIntercept);

        }
        else if(theta<CV_PI*10/180 || theta>CV_PI*170/180)
        {
            /*if(p<leftEdge[0])
             leftEdge = current;

             if(p>rightEdge[0])
             rightEdge = current;*/

            if(xIntercept>rightXIntercept)
            {
                rightEdge = current;
                rightXIntercept = xIntercept;
            }
            else if(xIntercept<=leftXIntercept)
            {
                leftEdge = current;
                leftXIntercept = xIntercept;
            }
        }
    }


    drawLine(topEdge, outerBox, CV_RGB(0,0,0));
    drawLine(bottomEdge, outerBox, CV_RGB(0,0,0));
    drawLine(leftEdge, outerBox, CV_RGB(0,0,0));
    drawLine(rightEdge, outerBox, CV_RGB(0,0,0));

    cv::Point left1, left2, right1, right2, bottom1, bottom2, top1, top2;

    int height=outerBox.size().height;
    int width=outerBox.size().width;

    if(leftEdge[1]!=0)
    {
        left1.x=0;      left1.y=leftEdge[0]/sin(leftEdge[1]);
        left2.x=width;  left2.y=-left2.x/tan(leftEdge[1]) + left1.y;
    }
    else
    {
        left1.y=0;      left1.x=leftEdge[0]/cos(leftEdge[1]);
        left2.y=height; left2.x=left1.x - height*tan(leftEdge[1]);
    }

    if(rightEdge[1]!=0)
    {
        right1.x=0;     right1.y=rightEdge[0]/sin(rightEdge[1]);
        right2.x=width; right2.y=-right2.x/tan(rightEdge[1]) + right1.y;
    }
    else
    {
        right1.y=0;     right1.x=rightEdge[0]/cos(rightEdge[1]);
        right2.y=height;    right2.x=right1.x - height*tan(rightEdge[1]);
    }

    bottom1.x=0;    bottom1.y=bottomEdge[0]/sin ...
(more)
edit retag flag offensive close merge delete