I am trying to compare two images (determine whether they are similar or not) using the OpenCV library. I configured the java wrapper and found several tutorials (mostly in C/C++) that I am trying to rewrite into Java. I am using the feature detection approach.
The problem is that the algorithm that I currently have does not produce any reasonable results (it claims that two similar images have nothing in common and finds matches between other two images that are completely different). Could someone suggest how should I use the openCV matcher to produce some reasonable results?
This is my code for the image comparison
private static void compareImages(String path1, String path2) {
System.out.println(path1 + "-" + path2);
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
// first image
Mat img1 = Imgcodecs.imread(path1, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
Mat descriptors1 = new Mat();
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
detector.detect(img1, keypoints1);
descriptor.compute(img1, keypoints1, descriptors1);
// second image
Mat img2 = Imgcodecs.imread(path2, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
Mat descriptors2 = new Mat();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
detector.detect(img2, keypoints2);
descriptor.compute(img2, keypoints2, descriptors2);
// match these two keypoints sets
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
for (DMatch m : matches.toArray()) {
// how to use these values to detect the similarity? They seem to be way off
// all of these values are in range 50-80 which seems wrong to me
System.out.println(m.distance);
}
}
Unfortunately, algorithms like SURF and SIFT are not available in the java wrapper so I am using ORB. I have little to no experience with computer vision, I am just trying to get this simple comparison algorithm work to produce some reasonable outcome. I would be glad for any help!
EDIT: My use-case is running this algorithm against images taken from different angles. I updated my code to be better formatted.
Sample images to compare:
Just my two cents:
There is access to SURF and SIFT in java: openCV DescriptorExtractor Reference. I tried the FREAK implementation three years back and found out, that there is some change happening to the binary descriptor when openCV passes them over to Java. It may be that ORB is subject to the same problem. Did you compare the data of the descriptors from c or c++ to the ones on the java side?
The brute force matcher finds the best matching feature from the train image for EVERY feature in the query image. Even if it looks completely different. You have to sift through the matches and drop bad ones. There exist several strategies, an easy one would be to just take the best 20% of the matches (but this will not drop ALL outlier). Progressive Sample Consensus performed very well in my setup.
Calib3d.findHomography(obj, scene, CV_RANSAC);
and use a normalized pixel difference of the overlapping areas.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With