0

I want to find the corner position of an blurred image with a corner inside it. like the following example:

Blurred image example

I can make sure that only one corner is inside the image, and I assume that

the corner is part of a black and white chessboard.

How can I detect the cross position with openCV? Thanks!

pagid
  • 13,559
  • 11
  • 78
  • 104
XU Bin
  • 251
  • 3
  • 6

3 Answers3

0

Usually you can determine the corner using the gradient:

Gx = im[i][j+1] - im[i][j-1]; Gy = im[i+1][j] – im[i-1][j];

G^2 = Gx^2 + Gy^2;

teta = atan2 (Gy, Gx);

As your image is blurred, you should compute the gradient at a larger scale:

Gx = im[i][j+delta] - im[i][j-delta]; Gy = im[i+ delta][j] – im[i- delta][j];

Here is the result that I obtained for delta = 50:

The gradient norm (multiplied by 20)

gradient norm http://imageshack.us/scaled/thumb/822/xdpp.jpg

The gradient direction:

gradient direction http://imageshack.us/scaled/thumb/844/h6zp.jpg

Raluca
  • 280
  • 2
  • 9
0

another solution

enter image description here

#include <opencv2/opencv.hpp>

using namespace cv;
int main()
{

    Mat img=imread("c:/data/corner.jpg");
    Mat gray;
    cvtColor(img,gray,CV_BGR2GRAY);
    threshold(gray,gray,100,255,CV_THRESH_BINARY);
    int step=15;
    std::vector<Point> points;
    for(int i=0;i<gray.rows;i+=step)
        for(int j=0;j<gray.cols;j+=step)
            if(gray.at<uchar>(i,j)==255)            
                points.push_back(Point(j,i));

    //fit a rotated rectangle

    RotatedRect box = minAreaRect(Mat(points));
    //circle(img,box.center,2,Scalar(255,0,0),-1);

    //invert it,fit again and get average of centers(may not be needed if a 'good' threshold is found)
    Point p1=Point(box.center.x,box.center.y);
    points.clear();
    gray=255-gray;
    for(int i=0;i<gray.rows;i+=step)
        for(int j=0;j<gray.cols;j+=step)
            if(gray.at<uchar>(i,j)==255)
                points.push_back(Point(j,i));
    box = minAreaRect(Mat(points));
    Point p2=Point(box.center.x,box.center.y);

    //circle(img,p2,2,Scalar(0,255,0),-1);
    circle(img,Point((p1.x+p2.x)/2,(p1.y+p2.y)/2),3,Scalar(0,0,255),-1);
    imshow("img",img);
    waitKey();

    return 0;
}
Zaw Lin
  • 5,629
  • 1
  • 23
  • 41
  • Great work! Thanks a lot. Well... I can't understand your method very well. Could you please explain it briefly? Thanks again. – XU Bin Oct 30 '13 at 03:07
0

Rather than work right away at a ridiculously large scale, as suggested by others, I recommend downsizing first (which has the effect of deblurring), do one pass of Harris to find the corner, then upscale its position and do a pass of findCornerSubpix at full resolution with a large window (large enough to encompass the obvious saddle point of the intensity).

In this way you get the best of both worlds: fast detection to initialize the refinement, and accurate refinement given the original imagery.

See also this other relevant answer

Community
  • 1
  • 1
Francesco Callari
  • 11,300
  • 2
  • 25
  • 40
  • Thanks buddy! I have been try that before. Actually it's ok to find the rough position of corner with downscale image. However, results is no good with findCornerSubpix to locate the precise position. I think I maybe have to implement a new subpix finding function. – XU Bin Oct 30 '13 at 03:05
  • Surprising! How exactly does findCornerSubpix behave (at full resolution, after initializing with the rough position)? Does it converge to some random place, or near a plausible saddle point, but not close enough? Have you tried increasing the number of iterations? – Francesco Callari Oct 30 '13 at 03:16
  • To clarify, your image does have an obvious saddle point, and findCornerSubpix should easily converge to it. See what it looks like when the intensity is plotted in 3d: http://i.imgur.com/xuVOmU6.jpg – Francesco Callari Oct 30 '13 at 03:42