Tuesday, September 22, 2015

[OpenCV] Comparing Image Similarity Using Feature Matching In Java



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.


The return value is the count of the distance under 10.
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.


14 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/lang/String;I)J
    at org.opencv.imgcodecs.Imgcodecs.imread_0(Native Method)
    at org.opencv.imgcodecs.Imgcodecs.imread(Imgcodecs.java:93)
    at imagecomparator.Mini.compareFeature(Mini.java:62)
    at imagecomparator.Mini.main(Mini.java:37)
    Java Result: 1

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. import org.opencv.core.DMatch cannot be resolved
    import org.opencv.imgcodecs.Imgcodecs cannot be resolved

    I found every where I added this opencv_library-2.4.3.jar file too.. still getting eroor.

    plz help.

    ReplyDelete
  5. Hy all
    Can this code compare camera captured image with computer generated images??

    ReplyDelete
  6. DOWNLOAD JAR FILE FROM HERE

    https://mvnrepository.com/artifact/nu.pattern/opencv/2.4.9-4

    ReplyDelete
  7. Its truely Very good n helpful program i ever ever seen!
    Thank you much small word for you.
    will you give me your mail id?I just want to discuss on some issues.
    Thanks n Keep sharing

    ReplyDelete
  8. if I select similar kind of two images but both images are have different size,color and structure but same type of contents like(2 type of rose images),then how can i compare both images please suggest me java code for that

    ReplyDelete
  9. Hello,I also want java code with opencv same as your problem...
    If you found any java code for this plz share to me..
    Thank you...

    ReplyDelete
  10. Hi, I am using your code to compare two images, but facing problem whenever, I am resizing the Image1 using java code, before performing the image comparison. Notice below execution result, for Image1 to col is coming as 0. But if I do not resize Image1 before executing the code, Image1's col is coming as 32. How to overcome this problem?
    Type of Image1= 0, Type of Image2= 0
    Cols of Image1= 0, Cols of Image2= 32
    estimatedTime=62ms
    Two images are different.

    ReplyDelete
  11. Hi, I want to get a match value for slightly different images but this returns 0, how to alter the code to get a match value for slightly different images?

    ReplyDelete
  12. Hi, I want to compare two images which are same but one is b/w format and the other one is color image, can you send me the java code for this requirement..

    ReplyDelete