I am trying to automatically decide wether two figures are similar or not. You can find three examples here:
https://i.stack.imgur.com/09Zqf.png
The first image is different from the second and third image, but the second and third are the same (not identical, if you look closely, there are some small differences)
My code (most of it is from the feature homography example in the OpenCV documentation) reads two different images, computes their keypoints and descriptors (using SIFT, but I have also tried SURF and ORB), matches them using the FlannBasedMatcher and computes the homography matrix. From the optional status vector I compute the ratio of inliers over the total number of keypoints in order to compute a ‘distance’.
However, the distances calculated do not make the correct distinction:
d(img1, img2) = 0.296296
d(img1, img3) = 0.407407
d(img2, img3) = 0.362069
So I am unable to conclude that image 1 is different from image 2, image 1 is different from image 2 and image 2 is equal to image 3.
Is there a better method or metric to decide which images are similar?
Mat img_object = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_scene = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
//-- Step 1: Detect keypoints using SIFT
Ptr<FeatureDetector > detector;
detector = new SiftFeatureDetector();
std::vector<KeyPoint> keypoints_object, keypoints_scene;
detector->detect( img_object, keypoints_object );
detector->detect( img_scene, keypoints_scene );
//-- Step 2: Calculate descriptors (feature vectors)
Ptr<DescriptorExtractor > extractor;
extractor = new SiftDescriptorExtractor;
Mat descriptors_object, descriptors_scene;
extractor->compute( img_object, keypoints_object, descriptors_object );
extractor->compute( img_scene, keypoints_scene, descriptors_scene );
//-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches );
//-- Step 4: Compute homography matrix and status vector
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( int i = 0; i<matches.size(); i++){
obj.push_back( keypoints_object[ matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ matches[i].trainIdx ].pt );
}
std::vector<uchar> status;
Mat H = findHomography( obj, scene, status, CV_RANSAC, 3 );
//-- Step 5: Compute inliers/status.size
int inliers = 0;
for(int i = 0; i<status.size(); i++){
inliers += status[i];
}
printf("Percentage of inliers: %f \n",( (float) inliers)/( (float) status.size() ));
Why don’t you just find all circles and calculate distance between them?
Here’s code:
And results: