Ask Your Question
1

Problem with Harris corner detection on thinned image

asked 2015-07-24 05:04:11 -0600

A new problem in my software arises :)

I got this input image, a skeletonized fingerprint

image description

Then I am running Harris corner detection like in this example with the following code

cornerHarris(input_thinned, harris_corners, 2, 3, 0.04, BORDER_DEFAULT);
normalize(harris_corners, harris_corners_normalised, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(harris_corners_normalised, harris_corners_normalised);

And then I select all keypoint higher than 125 by this

int threshold = 125;
vector<KeyPoint> keypoints;
// Make a color clone for visualisation purposes
Mat harris_clone = harris_corners_normalised.clone();
harris_clone.convertTo(harris_clone, CV_8UC1);
cvtColor(harris_clone, harris_clone, CV_GRAY2BGR);
for(int i=0; i<harris_corners_normalised.rows; i++){
   for(int j=0; j<harris_corners_normalised.cols; j++){
      if ( (int)harris_corners_normalised.at<float>(j, i) > threshold ){
         // Draw or store the keypoint location here, just like you decide. In our case we will store the location of the keypoint
         circle(harris_clone, Point(i, j), 5, Scalar(0,255,0), 1);
         circle(harris_clone, Point(i, j), 1, Scalar(0,0,255), 1);
         keypoints.push_back( KeyPoint (i, j, 1) );
      }
   }
}
imshow("temp", harris_clone); waitKey(0);

And this is the result

image description

It seems to me that somewhere along the track, I got the point but they seem to be multiplied 4 times ... anyone got a clue what is going wrong?

edit retag flag offensive close merge delete

Comments

1

your i's and j's are all the wrong way ;)

but the main prob seems to be this:

convertScaleAbs(harris_corners_normalised, harris_corners_normalised);

it basically converts to CV_8U, so the at<float>() later goes wrong. (just erase that line, you don't even need it. the demo used that to make a drawable img for viz.)

image description

berak gravatar imageberak ( 2015-07-24 05:47:11 -0600 )edit

Hmm strange, found what was causing it ... if i replace

Mat harris_clone = harris_corners_normalised.clone();
harris_clone.convertTo(harris_clone, CV_8UC1);
cvtColor(harris_clone, harris_clone, CV_GRAY2BGR);

by

Mat harris_scaled_c(harris_scaled.rows, harris_scaled.cols, CV_8UC3);
Mat in[] = { harris_scaled, harris_scaled, harris_scaled };
int from_to[] = { 0,0, 1,1, 2,2 };
mixChannels( in, 3, &harris_scaled_c, 1, from_to, 3 );

Then i get the exact same result.

StevenPuttemans gravatar imageStevenPuttemans ( 2015-07-24 05:49:21 -0600 )edit

And actually if I remove the abs conversion than it crashes ...

StevenPuttemans gravatar imageStevenPuttemans ( 2015-07-24 05:51:08 -0600 )edit

Hmm let me reconsider my answer :D I got it to work and now it completely gone again ... let me try to follow your guidelines and get back to you.

StevenPuttemans gravatar imageStevenPuttemans ( 2015-07-24 05:55:46 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2015-07-24 06:02:33 -0600

As suggested by @berak, after fixing indexing and conversion, the following result works flawlessly

// Now lets detect the strong minutiae using Haris corner detection
Mat harris_corners, harris_normalised;
harris_corners = Mat::zeros(input_thinned.size(), CV_32FC1);
cornerHarris(input_thinned, harris_corners, 2, 3, 0.04, BORDER_DEFAULT);
normalize(harris_corners, harris_normalised, 0, 255, NORM_MINMAX, CV_32FC1, Mat());

// Select the strongest corners that you want
int threshold = 125;
vector<KeyPoint> keypoints;

// Make a color clone for visualisation purposes
Mat rescaled;
convertScaleAbs(harris_normalised, rescaled);
Mat harris_c(rescaled.rows, rescaled.cols, CV_8UC3);
Mat in[] = { rescaled, rescaled, rescaled };
int from_to[] = { 0,0, 1,1, 2,2 };
mixChannels( in, 3, &harris_c, 1, from_to, 3 );

for(int x=0; x<harris_normalised.cols; x++){
   for(int y=0; y<harris_normalised.rows; y++){
      if ( (int)harris_normalised.at<float>(y, x) > threshold ){
         // Draw or store the keypoint location here, just like you decide. In our case we will store the location of the keypoint
         circle(harris_c, Point(x, y), 5, Scalar(0,255,0), 1);
         circle(harris_c, Point(x, y), 1, Scalar(0,0,255), 1);
         keypoints.push_back( KeyPoint (x, y, 1) );
      }
   }
}
imshow("temp", harris_c); waitKey(0);
edit flag offensive delete link more

Comments

@berak, I have little experience with binary descriptors, so I was wondering, on the positions retrieved I would now call the sift descriptor, but is that actually a good choice given the fact that I got a binarized skeleton image?

StevenPuttemans gravatar imageStevenPuttemans ( 2015-07-24 06:11:45 -0600 )edit

@StevenPuttemans: you can use SIFT with binarized images, the gradients will be encoded and this is what you typically want.

Guanta gravatar imageGuanta ( 2015-07-25 11:56:41 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-07-24 05:04:11 -0600

Seen: 1,052 times

Last updated: Jul 24 '15