Path: blob/master/samples/java/tutorial_code/features2D/akaze_matching/AKAZEMatchDemo.java
16354 views
import java.io.File;1import java.io.IOException;2import java.util.ArrayList;3import java.util.List;45import javax.xml.parsers.DocumentBuilder;6import javax.xml.parsers.DocumentBuilderFactory;7import javax.xml.parsers.ParserConfigurationException;89import org.opencv.core.Core;10import org.opencv.core.CvType;11import org.opencv.core.DMatch;12import org.opencv.core.KeyPoint;13import org.opencv.core.Mat;14import org.opencv.core.MatOfDMatch;15import org.opencv.core.MatOfKeyPoint;16import org.opencv.core.Scalar;17import org.opencv.features2d.AKAZE;18import org.opencv.features2d.DescriptorMatcher;19import org.opencv.features2d.Features2d;20import org.opencv.highgui.HighGui;21import org.opencv.imgcodecs.Imgcodecs;22import org.w3c.dom.Document;23import org.xml.sax.SAXException;2425class AKAZEMatch {26public void run(String[] args) {27//! [load]28String filename1 = args.length > 2 ? args[0] : "../data/graf1.png";29String filename2 = args.length > 2 ? args[1] : "../data/graf3.png";30String filename3 = args.length > 2 ? args[2] : "../data/H1to3p.xml";31Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.IMREAD_GRAYSCALE);32Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.IMREAD_GRAYSCALE);33if (img1.empty() || img2.empty()) {34System.err.println("Cannot read images!");35System.exit(0);36}3738File file = new File(filename3);39DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();40DocumentBuilder documentBuilder;41Document document;42Mat homography = new Mat(3, 3, CvType.CV_64F);43double[] homographyData = new double[(int) (homography.total()*homography.channels())];44try {45documentBuilder = documentBuilderFactory.newDocumentBuilder();46document = documentBuilder.parse(file);47String homographyStr = document.getElementsByTagName("data").item(0).getTextContent();48String[] splited = homographyStr.split("\\s+");49int idx = 0;50for (String s : splited) {51if (!s.isEmpty()) {52homographyData[idx] = Double.parseDouble(s);53idx++;54}55}56} catch (ParserConfigurationException e) {57e.printStackTrace();58System.exit(0);59} catch (SAXException e) {60e.printStackTrace();61System.exit(0);62} catch (IOException e) {63e.printStackTrace();64System.exit(0);65}66homography.put(0, 0, homographyData);67//! [load]6869//! [AKAZE]70AKAZE akaze = AKAZE.create();71MatOfKeyPoint kpts1 = new MatOfKeyPoint(), kpts2 = new MatOfKeyPoint();72Mat desc1 = new Mat(), desc2 = new Mat();73akaze.detectAndCompute(img1, new Mat(), kpts1, desc1);74akaze.detectAndCompute(img2, new Mat(), kpts2, desc2);75//! [AKAZE]7677//! [2-nn matching]78DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);79List<MatOfDMatch> knnMatches = new ArrayList<>();80matcher.knnMatch(desc1, desc2, knnMatches, 2);81//! [2-nn matching]8283//! [ratio test filtering]84float ratioThreshold = 0.8f; // Nearest neighbor matching ratio85List<KeyPoint> listOfMatched1 = new ArrayList<>();86List<KeyPoint> listOfMatched2 = new ArrayList<>();87List<KeyPoint> listOfKeypoints1 = kpts1.toList();88List<KeyPoint> listOfKeypoints2 = kpts2.toList();89for (int i = 0; i < knnMatches.size(); i++) {90DMatch[] matches = knnMatches.get(i).toArray();91float dist1 = matches[0].distance;92float dist2 = matches[1].distance;93if (dist1 < ratioThreshold * dist2) {94listOfMatched1.add(listOfKeypoints1.get(matches[0].queryIdx));95listOfMatched2.add(listOfKeypoints2.get(matches[0].trainIdx));96}97}98//! [ratio test filtering]99100//! [homography check]101double inlierThreshold = 2.5; // Distance threshold to identify inliers with homography check102List<KeyPoint> listOfInliers1 = new ArrayList<>();103List<KeyPoint> listOfInliers2 = new ArrayList<>();104List<DMatch> listOfGoodMatches = new ArrayList<>();105for (int i = 0; i < listOfMatched1.size(); i++) {106Mat col = new Mat(3, 1, CvType.CV_64F);107double[] colData = new double[(int) (col.total() * col.channels())];108colData[0] = listOfMatched1.get(i).pt.x;109colData[1] = listOfMatched1.get(i).pt.y;110colData[2] = 1.0;111col.put(0, 0, colData);112113Mat colRes = new Mat();114Core.gemm(homography, col, 1.0, new Mat(), 0.0, colRes);115colRes.get(0, 0, colData);116Core.multiply(colRes, new Scalar(1.0 / colData[2]), col);117col.get(0, 0, colData);118119double dist = Math.sqrt(Math.pow(colData[0] - listOfMatched2.get(i).pt.x, 2) +120Math.pow(colData[1] - listOfMatched2.get(i).pt.y, 2));121122if (dist < inlierThreshold) {123listOfGoodMatches.add(new DMatch(listOfInliers1.size(), listOfInliers2.size(), 0));124listOfInliers1.add(listOfMatched1.get(i));125listOfInliers2.add(listOfMatched2.get(i));126}127}128//! [homography check]129130//! [draw final matches]131Mat res = new Mat();132MatOfKeyPoint inliers1 = new MatOfKeyPoint(listOfInliers1.toArray(new KeyPoint[listOfInliers1.size()]));133MatOfKeyPoint inliers2 = new MatOfKeyPoint(listOfInliers2.toArray(new KeyPoint[listOfInliers2.size()]));134MatOfDMatch goodMatches = new MatOfDMatch(listOfGoodMatches.toArray(new DMatch[listOfGoodMatches.size()]));135Features2d.drawMatches(img1, inliers1, img2, inliers2, goodMatches, res);136Imgcodecs.imwrite("akaze_result.png", res);137138double inlierRatio = listOfInliers1.size() / (double) listOfMatched1.size();139System.out.println("A-KAZE Matching Results");140System.out.println("*******************************");141System.out.println("# Keypoints 1: \t" + listOfKeypoints1.size());142System.out.println("# Keypoints 2: \t" + listOfKeypoints2.size());143System.out.println("# Matches: \t" + listOfMatched1.size());144System.out.println("# Inliers: \t" + listOfInliers1.size());145System.out.println("# Inliers Ratio: \t" + inlierRatio);146147HighGui.imshow("result", res);148HighGui.waitKey();149//! [draw final matches]150151System.exit(0);152}153}154155public class AKAZEMatchDemo {156public static void main(String[] args) {157// Load the native OpenCV library158System.loadLibrary(Core.NATIVE_LIBRARY_NAME);159160new AKAZEMatch().run(args);161}162}163164165