Path: blob/master/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java
16354 views
import java.util.ArrayList;1import java.util.List;23import org.opencv.calib3d.Calib3d;4import org.opencv.core.Core;5import org.opencv.core.CvType;6import org.opencv.core.DMatch;7import org.opencv.core.KeyPoint;8import org.opencv.core.Mat;9import org.opencv.core.MatOfByte;10import org.opencv.core.MatOfDMatch;11import org.opencv.core.MatOfKeyPoint;12import org.opencv.core.MatOfPoint2f;13import org.opencv.core.Point;14import org.opencv.core.Scalar;15import org.opencv.features2d.DescriptorMatcher;16import org.opencv.features2d.Features2d;17import org.opencv.highgui.HighGui;18import org.opencv.imgcodecs.Imgcodecs;19import org.opencv.imgproc.Imgproc;20import org.opencv.xfeatures2d.SURF;2122class SURFFLANNMatchingHomography {23public void run(String[] args) {24String filenameObject = args.length > 1 ? args[0] : "../data/box.png";25String filenameScene = args.length > 1 ? args[1] : "../data/box_in_scene.png";26Mat imgObject = Imgcodecs.imread(filenameObject, Imgcodecs.IMREAD_GRAYSCALE);27Mat imgScene = Imgcodecs.imread(filenameScene, Imgcodecs.IMREAD_GRAYSCALE);28if (imgObject.empty() || imgScene.empty()) {29System.err.println("Cannot read images!");30System.exit(0);31}3233//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors34double hessianThreshold = 400;35int nOctaves = 4, nOctaveLayers = 3;36boolean extended = false, upright = false;37SURF detector = SURF.create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);38MatOfKeyPoint keypointsObject = new MatOfKeyPoint(), keypointsScene = new MatOfKeyPoint();39Mat descriptorsObject = new Mat(), descriptorsScene = new Mat();40detector.detectAndCompute(imgObject, new Mat(), keypointsObject, descriptorsObject);41detector.detectAndCompute(imgScene, new Mat(), keypointsScene, descriptorsScene);4243//-- Step 2: Matching descriptor vectors with a FLANN based matcher44// Since SURF is a floating-point descriptor NORM_L2 is used45DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);46List<MatOfDMatch> knnMatches = new ArrayList<>();47matcher.knnMatch(descriptorsObject, descriptorsScene, knnMatches, 2);4849//-- Filter matches using the Lowe's ratio test50float ratioThresh = 0.75f;51List<DMatch> listOfGoodMatches = new ArrayList<>();52for (int i = 0; i < knnMatches.size(); i++) {53if (knnMatches.get(i).rows() > 1) {54DMatch[] matches = knnMatches.get(i).toArray();55if (matches[0].distance < ratioThresh * matches[1].distance) {56listOfGoodMatches.add(matches[0]);57}58}59}60MatOfDMatch goodMatches = new MatOfDMatch();61goodMatches.fromList(listOfGoodMatches);6263//-- Draw matches64Mat imgMatches = new Mat();65Features2d.drawMatches(imgObject, keypointsObject, imgScene, keypointsScene, goodMatches, imgMatches, Scalar.all(-1),66Scalar.all(-1), new MatOfByte(), Features2d.NOT_DRAW_SINGLE_POINTS);6768//-- Localize the object69List<Point> obj = new ArrayList<>();70List<Point> scene = new ArrayList<>();7172List<KeyPoint> listOfKeypointsObject = keypointsObject.toList();73List<KeyPoint> listOfKeypointsScene = keypointsScene.toList();74for (int i = 0; i < listOfGoodMatches.size(); i++) {75//-- Get the keypoints from the good matches76obj.add(listOfKeypointsObject.get(listOfGoodMatches.get(i).queryIdx).pt);77scene.add(listOfKeypointsScene.get(listOfGoodMatches.get(i).trainIdx).pt);78}7980MatOfPoint2f objMat = new MatOfPoint2f(), sceneMat = new MatOfPoint2f();81objMat.fromList(obj);82sceneMat.fromList(scene);83double ransacReprojThreshold = 3.0;84Mat H = Calib3d.findHomography( objMat, sceneMat, Calib3d.RANSAC, ransacReprojThreshold );8586//-- Get the corners from the image_1 ( the object to be "detected" )87Mat objCorners = new Mat(4, 1, CvType.CV_32FC2), sceneCorners = new Mat();88float[] objCornersData = new float[(int) (objCorners.total() * objCorners.channels())];89objCorners.get(0, 0, objCornersData);90objCornersData[0] = 0;91objCornersData[1] = 0;92objCornersData[2] = imgObject.cols();93objCornersData[3] = 0;94objCornersData[4] = imgObject.cols();95objCornersData[5] = imgObject.rows();96objCornersData[6] = 0;97objCornersData[7] = imgObject.rows();98objCorners.put(0, 0, objCornersData);99100Core.perspectiveTransform(objCorners, sceneCorners, H);101float[] sceneCornersData = new float[(int) (sceneCorners.total() * sceneCorners.channels())];102sceneCorners.get(0, 0, sceneCornersData);103104//-- Draw lines between the corners (the mapped object in the scene - image_2 )105Imgproc.line(imgMatches, new Point(sceneCornersData[0] + imgObject.cols(), sceneCornersData[1]),106new Point(sceneCornersData[2] + imgObject.cols(), sceneCornersData[3]), new Scalar(0, 255, 0), 4);107Imgproc.line(imgMatches, new Point(sceneCornersData[2] + imgObject.cols(), sceneCornersData[3]),108new Point(sceneCornersData[4] + imgObject.cols(), sceneCornersData[5]), new Scalar(0, 255, 0), 4);109Imgproc.line(imgMatches, new Point(sceneCornersData[4] + imgObject.cols(), sceneCornersData[5]),110new Point(sceneCornersData[6] + imgObject.cols(), sceneCornersData[7]), new Scalar(0, 255, 0), 4);111Imgproc.line(imgMatches, new Point(sceneCornersData[6] + imgObject.cols(), sceneCornersData[7]),112new Point(sceneCornersData[0] + imgObject.cols(), sceneCornersData[1]), new Scalar(0, 255, 0), 4);113114//-- Show detected matches115HighGui.imshow("Good Matches & Object detection", imgMatches);116HighGui.waitKey(0);117118System.exit(0);119}120}121122public class SURFFLANNMatchingHomographyDemo {123public static void main(String[] args) {124// Load the native OpenCV library125System.loadLibrary(Core.NATIVE_LIBRARY_NAME);126127new SURFFLANNMatchingHomography().run(args);128}129}130131132