Ask Your Question

Revision history [back]

Removing outliers from Similar Images

Hello..

I am implementing a java program that highlights the difference between two images.

I used the following steps :

  1. turning the images into gray scale
  2. apply feature detection to the images in order to check if they are similar
  3. applying absdiff to them
  4. highlighting the difference in the original picture

My problem is : when I upload two images that are similar but one of them have outliers, or the position is slightly different , the whole image become different

the code is : ` package image;

import org.opencv.calib3d.Calib3d;
import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.features2d.DMatch;
import org.opencv.features2d.KeyPoint;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;




import java.awt.image.BufferedImage;

import java.io.File;
import java.io.IOException; 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;


public class SURFDetector22 {

 boolean answer;



 //copy matrix
 public static Mat imitate(Mat m){
        return new Mat(m.height(), m.width(), m.type());
    }

 //draw rect
  public static void drawRotatedRect(Mat image, RotatedRect rotatedRect, Scalar color, int thickness) {
      Point[] vertices = new Point[4];
      rotatedRect.points(vertices);
      MatOfPoint points = new MatOfPoint(vertices);
      Imgproc.drawContours(image, Arrays.asList(points), -1, color, thickness);
  }


  //diff btw matrices
 public static Mat diff(Mat mat1, Mat mat2){
        Mat dst = imitate(mat1);
        Core.absdiff(mat1, mat2, dst);
        return dst;}

public  void imageComparison(File file1, File file2) throws IOException {

    File lib = null;
    String os = System.getProperty("os.name");
    String bitness = System.getProperty("sun.arch.data.model");

    if (os.toUpperCase().contains("WINDOWS")) {
        if (bitness.endsWith("64")) {
            lib = new File("libs//x64//" + System.mapLibraryName("opencv_java2411"));
        } else {
            lib = new File("libs//x86//" + System.mapLibraryName("opencv_java2411"));
        }
    }

    System.loadLibrary( Core.NATIVE_LIBRARY_NAME );

    ///////step 1 : read images

    ///first image
    String bookObject = file1.getAbsolutePath();    
    Mat objectImage = Highgui.imread(bookObject, Highgui.CV_LOAD_IMAGE_COLOR);
     Mat mat1 = new Mat(objectImage.height(),objectImage.width(),CvType.CV_8UC1);
    Imgproc.cvtColor(objectImage, mat1, Imgproc.COLOR_RGB2GRAY);


    byte[] data1 = new byte[mat1.rows() * mat1.cols() * (int)(mat1.elemSize())];
    mat1.get(0, 0, data1);
    BufferedImage image1 = new BufferedImage(mat1.cols(),mat1.rows(), BufferedImage.TYPE_BYTE_GRAY);
    image1.getRaster().setDataElements(0, 0, mat1.cols(), mat1.rows(), data1);

    File ouptut = new File("gray//1.jpg");
    ImageIO.write(image1, "jpg", ouptut);

    //bade a3ml show la hyde el sora

    //2nd image
    String bookScene = file2.getAbsolutePath();
    Mat sceneImage = Highgui.imread(bookScene, Highgui.CV_LOAD_IMAGE_COLOR);
    Mat mat2 = new Mat(sceneImage.height(),sceneImage.width(),CvType.CV_8UC1);
  Imgproc.cvtColor(sceneImage, mat2, Imgproc.COLOR_RGB2GRAY );

  byte[] data2 = new byte[mat2.rows() * mat2.cols() * (int)(mat2.elemSize())];
  mat2.get(0, 0, data2);
  BufferedImage image2 = new BufferedImage(mat2.cols(),mat2.rows(), BufferedImage.TYPE_BYTE_GRAY);
  image2.getRaster().setDataElements(0, 0, mat2.cols(), mat2.rows(), data2);

  File ouptut2 = new File("gray//2.jpg");
  ImageIO.write(image2, "jpg", ouptut2);

  //////step 2 : Detect and extract features


  MatOfKeyPoint objectKeyPoints = new MatOfKeyPoint();
    FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.SURF);
    System.out.println("Detecting key points...");
    featureDetector.detect(mat1, objectKeyPoints);
    System.out.println("----- key pointss image 1----" + objectKeyPoints);
    //KeyPoint[] keypoints = objectKeyPoints.toArray();
    System.out.println(objectKeyPoints);

    MatOfKeyPoint objectDescriptors = new MatOfKeyPoint();
    DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.SURF);
    System.out.println("Computing descriptors...");
    descriptorExtractor.compute(objectImage, objectKeyPoints, objectDescriptors);


    // Create the matrix for output image.
    Mat outputImage = new Mat(objectImage.rows(), objectImage.cols(), Highgui.CV_LOAD_IMAGE_COLOR);
    Scalar newKeypointColor = new Scalar(255, 0, 0);

    System.out.println("Drawing key points on object image...");
    Features2d.drawKeypoints(objectImage, objectKeyPoints, outputImage, newKeypointColor, 0);

    // Match object image with the scene image
    MatOfKeyPoint sceneKeyPoints = new MatOfKeyPoint();
    MatOfKeyPoint sceneDescriptors = new MatOfKeyPoint();
    System.out.println("Detecting key points in background image...");
    featureDetector.detect(mat2, sceneKeyPoints);
    System.out.println("----img2 key pointys----" + sceneKeyPoints);
    System.out.println("Computing descriptors in background image...");
    descriptorExtractor.compute(mat2, sceneKeyPoints, sceneDescriptors);

    Mat matchoutput = new Mat(mat2.rows() * 2, mat2.cols() * 2, Highgui.CV_LOAD_IMAGE_COLOR);
    Scalar matchestColor = new Scalar(0, 255, 0);

    List<MatOfDMatch> matches = new LinkedList<MatOfDMatch>();
    DescriptorMatcher descriptorMatcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
    System.out.println("Matching object and scene images...");
    descriptorMatcher.knnMatch(objectDescriptors, sceneDescriptors, matches, 2);

    System.out.println("Calculating good match list...");
    LinkedList<DMatch> goodMatchesList = new LinkedList<DMatch>();

    float nndrRatio = 0.7f;

    for (int i = 0; i < matches.size(); i++) {
        MatOfDMatch matofDMatch = matches.get(i);
        DMatch[] dmatcharray = matofDMatch.toArray();
        DMatch m1 = dmatcharray[0];
        DMatch m2 = dmatcharray[1];

        if (m1.distance <= m2.distance * nndrRatio) {
            goodMatchesList.addLast(m1);

        }
    }

    if (goodMatchesList.size() >= matches.size() - 1) {
        System.out.println("Object Found!!!");
        answer = true;

        List<KeyPoint> objKeypointlist = objectKeyPoints.toList();
        List<KeyPoint> scnKeypointlist = sceneKeyPoints.toList();

        LinkedList<Point> objectPoints = new LinkedList<>();
        LinkedList<Point> scenePoints = new LinkedList<>();

        for (int i = 0; i < goodMatchesList.size(); i++) {
            objectPoints.addLast(objKeypointlist.get(goodMatchesList.get(i).queryIdx).pt);
            scenePoints.addLast(scnKeypointlist.get(goodMatchesList.get(i).trainIdx).pt);
        }

        MatOfPoint2f objMatOfPoint2f = new MatOfPoint2f();
        objMatOfPoint2f.fromList(objectPoints);
        MatOfPoint2f scnMatOfPoint2f = new MatOfPoint2f();
        scnMatOfPoint2f.fromList(scenePoints);

        Mat homography = Calib3d.findHomography(objMatOfPoint2f, scnMatOfPoint2f, Calib3d.RANSAC, 3);

        Mat obj_corners = new Mat(4, 1, CvType.CV_32FC2);
        Mat scene_corners = new Mat(4, 1, CvType.CV_32FC2);

        obj_corners.put(0, 0, new double[] { 0, 0 });
        obj_corners.put(1, 0, new double[] { objectImage.cols(), 0 });
        obj_corners.put(2, 0, new double[] { objectImage.cols(), objectImage.rows() });
        obj_corners.put(3, 0, new double[] { 0, objectImage.rows() });

        System.out.println("Transforming object corners to scene corners...");
        Core.perspectiveTransform(obj_corners, scene_corners, homography);

        Mat img = Highgui.imread(bookScene, Highgui.CV_LOAD_IMAGE_COLOR);

        Core.line(img, new Point(scene_corners.get(0, 0)), new Point(scene_corners.get(1, 0)),
                new Scalar(0, 255, 0), 4);
        Core.line(img, new Point(scene_corners.get(1, 0)), new Point(scene_corners.get(2, 0)),
                new Scalar(0, 255, 0), 4);
        Core.line(img, new Point(scene_corners.get(2, 0)), new Point(scene_corners.get(3, 0)),
                new Scalar(0, 255, 0), 4);
        Core.line(img, new Point(scene_corners.get(3, 0)), new Point(scene_corners.get(0, 0)),
                new Scalar(0, 255, 0), 4);

        System.out.println("Drawing matches image...");
        MatOfDMatch goodMatches = new MatOfDMatch();
        goodMatches.fromList(goodMatchesList);

        Features2d.drawMatches(objectImage, objectKeyPoints, sceneImage, sceneKeyPoints, goodMatches, matchoutput,
                matchestColor, newKeypointColor, new MatOfByte(), 2);

        // Highgui.imwrite("output//outputImage.jpg", outputImage);
        // Highgui.imwrite("output//matchoutput.jpg", matchoutput);
        // Highgui.imwrite("output//img.jpg", img);
        // File f= new File("output");

        Highgui.imwrite("output//1.jpg", outputImage);
        Highgui.imwrite("output//2.jpg", matchoutput);
        Highgui.imwrite("output//3.jpg", img);
    } else {
        System.out.println("Object Not Found");
        answer = false;


        Mat res = diff(mat1,mat2);
         byte[] data3 = new byte[res.rows() * res.cols() * (int)(res.elemSize())];
            res.get(0, 0, data3);
            BufferedImage image3 = new BufferedImage(res.cols(),res.rows(), BufferedImage.TYPE_BYTE_GRAY);
            image3.getRaster().setDataElements(0, 0, res.cols(), res.rows(), data3);

            File ouptut3 = new File("gray//3.jpg");
            ImageIO.write(image3, "jpg", ouptut3);



        ////////////////////////////


            List <MatOfPoint> contours = new ArrayList<>();
            Mat dest = Mat.zeros(res.size(), CvType.CV_8UC3);
            Scalar white = new Scalar(255, 255, 255);

            // Find contours
            Imgproc.findContours(res, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);







            Scalar green = new Scalar(81, 190, 0);
            for (MatOfPoint contour: contours) {
                RotatedRect rotatedRect = Imgproc.minAreaRect(new MatOfPoint2f(contour.toArray()));
                drawRotatedRect(mat1, rotatedRect, green, 4);
            }



            byte[] data4 = new byte[mat1.rows() * mat1.cols() * (int)(mat1.elemSize())];
            mat1.get(0, 0, data4);
            BufferedImage image4 = new BufferedImage(mat1.cols(),mat1.rows(), BufferedImage.TYPE_BYTE_GRAY);
            image3.getRaster().setDataElements(0, 0, mat1.cols(), mat1.rows(), data4);

            File ouptut4 = new File("gray//4.jpg");
            ImageIO.write(image4, "jpg", ouptut4);




            /////////////////
        }






    System.out.println("Ended....");




   }
 }
   `