It's comparing image similarity using feature matching.
I've used OpenCV and converted c language to java.
The source is as follows:
package kr.co.acronym; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.DMatch; import org.opencv.core.Mat; import org.opencv.core.MatOfDMatch; import org.opencv.core.MatOfKeyPoint; import org.opencv.features2d.DescriptorExtractor; import org.opencv.features2d.DescriptorMatcher; import org.opencv.features2d.FeatureDetector; import org.opencv.imgcodecs.Imgcodecs; public class Mini { public static void main(String[] args) { // Set image path String filename1 = "C:\\images\\iphone1.jpeg"; String filename2 = "C:\\images\\iphone2.jpeg"; int ret; ret = compareFeature(filename1, filename2); if (ret > 0) { System.out.println("Two images are same."); } else { System.out.println("Two images are different."); } } /** * Compare that two images is similar using feature mapping * @author minikim * @param filename1 - the first image * @param filename2 - the second image * @return integer - count that has the similarity within images */ public static int compareFeature(String filename1, String filename2) { int retVal = 0; long startTime = System.currentTimeMillis(); System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // Load images to compare Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.CV_LOAD_IMAGE_COLOR); Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.CV_LOAD_IMAGE_COLOR); // Declare key point of images MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); Mat descriptors1 = new Mat(); Mat descriptors2 = new Mat(); // Definition of ORB key point detector and descriptor extractors FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB); // Detect key points detector.detect(img1, keypoints1); detector.detect(img2, keypoints2); // Extract descriptors extractor.compute(img1, keypoints1, descriptors1); extractor.compute(img2, keypoints2, descriptors2); // Definition of descriptor matcher DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); // Match points of two images MatOfDMatch matches = new MatOfDMatch(); // System.out.println("Type of Image1= " + descriptors1.type() + ", Type of Image2= " + descriptors2.type()); // System.out.println("Cols of Image1= " + descriptors1.cols() + ", Cols of Image2= " + descriptors2.cols()); // Avoid to assertion failed // Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) if (descriptors2.cols() == descriptors1.cols()) { matcher.match(descriptors1, descriptors2 ,matches); // Check matches of key points DMatch[] match = matches.toArray(); double max_dist = 0; double min_dist = 100; for (int i = 0; i < descriptors1.rows(); i++) { double dist = match[i].distance; if( dist < min_dist ) min_dist = dist; if( dist > max_dist ) max_dist = dist; } System.out.println("max_dist=" + max_dist + ", min_dist=" + min_dist); // Extract good images (distances are under 10) for (int i = 0; i < descriptors1.rows(); i++) { if (match[i].distance <= 10) { retVal++; } } System.out.println("matching count=" + retVal); } long estimatedTime = System.currentTimeMillis() - startTime; System.out.println("estimatedTime=" + estimatedTime + "ms"); return retVal; } }
I created a new function, compareFeature that is compared two images.
It calculates the distance of the feature in those images.
If you check the last of the source, I decide the similarity by the minimum distance of two images.
The distance value that I choose is 10.
But if you try more and more, the value is more precise.
If it is one more, I think that the two images are similar.
I tested next 3 images.
When I checked image1.jpeg and image1.jpeg, the result is identical.
If I checked image1.jpeg and image2.jpeg, the result is similar.
If I checked image1.jpeg and image3.jpeg, the result is not similar.