123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import java.io.File;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import javax.xml.parsers.DocumentBuilder;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.parsers.ParserConfigurationException;
- import org.opencv.core.Core;
- import org.opencv.core.CvType;
- import org.opencv.core.DMatch;
- import org.opencv.core.KeyPoint;
- import org.opencv.core.Mat;
- import org.opencv.core.MatOfDMatch;
- import org.opencv.core.MatOfKeyPoint;
- import org.opencv.core.Scalar;
- import org.opencv.features2d.AKAZE;
- import org.opencv.features2d.DescriptorMatcher;
- import org.opencv.features2d.Features2d;
- import org.opencv.highgui.HighGui;
- import org.opencv.imgcodecs.Imgcodecs;
- import org.w3c.dom.Document;
- import org.xml.sax.SAXException;
- class AKAZEMatch {
- public void run(String[] args) {
- //! [load]
- String filename1 = args.length > 2 ? args[0] : "../data/graf1.png";
- String filename2 = args.length > 2 ? args[1] : "../data/graf3.png";
- String filename3 = args.length > 2 ? args[2] : "../data/H1to3p.xml";
- Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.IMREAD_GRAYSCALE);
- Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.IMREAD_GRAYSCALE);
- if (img1.empty() || img2.empty()) {
- System.err.println("Cannot read images!");
- System.exit(0);
- }
- File file = new File(filename3);
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder documentBuilder;
- Document document;
- Mat homography = new Mat(3, 3, CvType.CV_64F);
- double[] homographyData = new double[(int) (homography.total()*homography.channels())];
- try {
- documentBuilder = documentBuilderFactory.newDocumentBuilder();
- document = documentBuilder.parse(file);
- String homographyStr = document.getElementsByTagName("data").item(0).getTextContent();
- String[] splited = homographyStr.split("\\s+");
- int idx = 0;
- for (String s : splited) {
- if (!s.isEmpty()) {
- homographyData[idx] = Double.parseDouble(s);
- idx++;
- }
- }
- } catch (ParserConfigurationException e) {
- e.printStackTrace();
- System.exit(0);
- } catch (SAXException e) {
- e.printStackTrace();
- System.exit(0);
- } catch (IOException e) {
- e.printStackTrace();
- System.exit(0);
- }
- homography.put(0, 0, homographyData);
- //! [load]
- //! [AKAZE]
- AKAZE akaze = AKAZE.create();
- MatOfKeyPoint kpts1 = new MatOfKeyPoint(), kpts2 = new MatOfKeyPoint();
- Mat desc1 = new Mat(), desc2 = new Mat();
- akaze.detectAndCompute(img1, new Mat(), kpts1, desc1);
- akaze.detectAndCompute(img2, new Mat(), kpts2, desc2);
- //! [AKAZE]
- //! [2-nn matching]
- DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
- List<MatOfDMatch> knnMatches = new ArrayList<>();
- matcher.knnMatch(desc1, desc2, knnMatches, 2);
- //! [2-nn matching]
- //! [ratio test filtering]
- float ratioThreshold = 0.8f; // Nearest neighbor matching ratio
- List<KeyPoint> listOfMatched1 = new ArrayList<>();
- List<KeyPoint> listOfMatched2 = new ArrayList<>();
- List<KeyPoint> listOfKeypoints1 = kpts1.toList();
- List<KeyPoint> listOfKeypoints2 = kpts2.toList();
- for (int i = 0; i < knnMatches.size(); i++) {
- DMatch[] matches = knnMatches.get(i).toArray();
- float dist1 = matches[0].distance;
- float dist2 = matches[1].distance;
- if (dist1 < ratioThreshold * dist2) {
- listOfMatched1.add(listOfKeypoints1.get(matches[0].queryIdx));
- listOfMatched2.add(listOfKeypoints2.get(matches[0].trainIdx));
- }
- }
- //! [ratio test filtering]
- //! [homography check]
- double inlierThreshold = 2.5; // Distance threshold to identify inliers with homography check
- List<KeyPoint> listOfInliers1 = new ArrayList<>();
- List<KeyPoint> listOfInliers2 = new ArrayList<>();
- List<DMatch> listOfGoodMatches = new ArrayList<>();
- for (int i = 0; i < listOfMatched1.size(); i++) {
- Mat col = new Mat(3, 1, CvType.CV_64F);
- double[] colData = new double[(int) (col.total() * col.channels())];
- colData[0] = listOfMatched1.get(i).pt.x;
- colData[1] = listOfMatched1.get(i).pt.y;
- colData[2] = 1.0;
- col.put(0, 0, colData);
- Mat colRes = new Mat();
- Core.gemm(homography, col, 1.0, new Mat(), 0.0, colRes);
- colRes.get(0, 0, colData);
- Core.multiply(colRes, new Scalar(1.0 / colData[2]), col);
- col.get(0, 0, colData);
- double dist = Math.sqrt(Math.pow(colData[0] - listOfMatched2.get(i).pt.x, 2) +
- Math.pow(colData[1] - listOfMatched2.get(i).pt.y, 2));
- if (dist < inlierThreshold) {
- listOfGoodMatches.add(new DMatch(listOfInliers1.size(), listOfInliers2.size(), 0));
- listOfInliers1.add(listOfMatched1.get(i));
- listOfInliers2.add(listOfMatched2.get(i));
- }
- }
- //! [homography check]
- //! [draw final matches]
- Mat res = new Mat();
- MatOfKeyPoint inliers1 = new MatOfKeyPoint(listOfInliers1.toArray(new KeyPoint[listOfInliers1.size()]));
- MatOfKeyPoint inliers2 = new MatOfKeyPoint(listOfInliers2.toArray(new KeyPoint[listOfInliers2.size()]));
- MatOfDMatch goodMatches = new MatOfDMatch(listOfGoodMatches.toArray(new DMatch[listOfGoodMatches.size()]));
- Features2d.drawMatches(img1, inliers1, img2, inliers2, goodMatches, res);
- Imgcodecs.imwrite("akaze_result.png", res);
- double inlierRatio = listOfInliers1.size() / (double) listOfMatched1.size();
- System.out.println("A-KAZE Matching Results");
- System.out.println("*******************************");
- System.out.println("# Keypoints 1: \t" + listOfKeypoints1.size());
- System.out.println("# Keypoints 2: \t" + listOfKeypoints2.size());
- System.out.println("# Matches: \t" + listOfMatched1.size());
- System.out.println("# Inliers: \t" + listOfInliers1.size());
- System.out.println("# Inliers Ratio: \t" + inlierRatio);
- HighGui.imshow("result", res);
- HighGui.waitKey();
- //! [draw final matches]
- System.exit(0);
- }
- }
- public class AKAZEMatchDemo {
- public static void main(String[] args) {
- // Load the native OpenCV library
- System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
- new AKAZEMatch().run(args);
- }
- }
|