Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

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.


Monday, September 30, 2013

The Function That Changes Global Time to Local Time in Java

The time zone is the issue when you make global service.

There are four time zone in U.S.
PSF:  Pacific Standard Time
MST: Mountain Standard Time
CST: Central Standard Time
EST: Eastern Standard Time

The function of transformation from UTC/GMT to local time

Sometimes you need to transform from standard time to local time.
You can use the function bellow.

 // Local Time -> UTC/GMT Time  
 public static long convertLocalTimeToUTC(long pv_localDateTime)  
 {  
   long lv_UTCTime = pv_localDateTime;  
     
   TimeZone z = TimeZone.getDefault();  
   //int offset = z.getRawOffset(); // The offset not includes daylight savings time  
   int offset = z.getOffset(pv_localDateTime); // The offset includes daylight savings time  
   lv_UTCTime = pv_localDateTime - offset;  
   return lv_UTCTime;  
 }  
   
 // UTC/GMT Time -> Local Time  
 public static long convertUTCToLocalTime(long pv_UTCDateTime)  
 {  
   long lv_localDateTime = pv_UTCDateTime;  
     
   TimeZone z = TimeZone.getDefault();  
   //int offset = z.getRawOffset(); // The offset not includes daylight savings time  
   int offset = z.getOffset(pv_UTCDateTime); // The offset includes daylight savings time  
     
   lv_localDateTime = pv_UTCDateTime + offset;  
     
   return lv_localDateTime;  
 }  
   

It is very easy to understand.
You carefully check that the parameter with long type is return value from getDate() method in Date format.


Transform from UTC/GMT to local time using Date Format

Actually there is a need to change the form of the type such as "20120713064755".
This is the solution using SimpleDateFormat.

 import java.text.ParseException;  
 import java.text.SimpleDateFormat;  
 import java.util.Date;  
 import java.util.TimeZone;  
   
 public class ConverTimeZone {  
   
      public static void main(String[] args) {  
           // changes from UTC to local time  
           //String utcTime = "20120713184755";  
           String utcTime = "20120713064755";  
             
           String localTime = convertUtcToLocal(utcTime);  
             
           System.out.println("GMT/UTC: " + utcTime + ", local time: " + localTime);  
      }  
   
      /**  
       * the function that changes from UTC to local time   
       * @author xmlmanager  
       * @param utcTime GMT/UTC (format: 20120713064755)  
       * @return String local time   
       */  
      private static String convertUtcToLocal(String utcTime) {  
           String localTime = "";  
             
           // declare date format   
           SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");  
             
           try {  
                // changes from UTC to Date format  
                Date dateUtcTime = dateFormat.parse(utcTime);  
                  
                // changes from UTC Date format to the time of long type  
                long longUtcTime = dateUtcTime.getTime();  
                  
                // calculate the difference through TimeZone (if it is summer time, use getOffset than getRawOffset)  
                TimeZone zone = TimeZone.getDefault();  
                int offset = zone.getOffset(longUtcTime);  
                long longLocalTime = longUtcTime + offset;  
                  
                // changes from local time of long type to Date format  
                Date dateLocalTime = new Date();  
                dateLocalTime.setTime(longLocalTime);  
                  
                // return the string of local time  
                localTime = dateFormat.format(dateLocalTime);  
                  
           } catch (ParseException e) {  
                e.printStackTrace();  
           }             
             
           return localTime;  
      }  
 }  
   

That's all!!

Sunday, September 29, 2013

The Tip of Programming Comment

There are two type of comments in java and C.
"//" is the inline comment and "/* .. */" is the block comment.

Sometimes mixing the two type of comments is very useful.

If you use like this, the first line is comment and second line runs.
/*
This is comment.
/*/
This runs.
//*/

When you add "/" in front of the "/*" at the beginning, it changes.

//*
This runs.
/*/
This is comment.
//*/

I used usually it when I need the test account.



Saturday, March 31, 2012

Some problems of float and double variables in java

You must not use the float or double datatype for accurate calculations.
At java programming, it doesn't get exact number to use the float or double datatype.

For example, if you had 1.03 dollars and used 42 cents, you remained 61 cents.
Using java programming answers as follows.


System.out.println(1.03 - .42);

---------- Execute ----------
0.6100000000000001

Not exactly what you want. 
Because the float and double was designed for science and engineering, it calculates so fast as an approximate value. 
So the float and double variables are imprecise. 

What you use for accurate calculations?
The answer is int, long, and bigdecimal. 

I refer to the book of effective java programming language guide.