SURFFLANNMatchingHomographyDemo.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import org.opencv.calib3d.Calib3d;
  4. import org.opencv.core.Core;
  5. import org.opencv.core.CvType;
  6. import org.opencv.core.DMatch;
  7. import org.opencv.core.KeyPoint;
  8. import org.opencv.core.Mat;
  9. import org.opencv.core.MatOfByte;
  10. import org.opencv.core.MatOfDMatch;
  11. import org.opencv.core.MatOfKeyPoint;
  12. import org.opencv.core.MatOfPoint2f;
  13. import org.opencv.core.Point;
  14. import org.opencv.core.Scalar;
  15. import org.opencv.features2d.DescriptorMatcher;
  16. import org.opencv.features2d.Features2d;
  17. import org.opencv.highgui.HighGui;
  18. import org.opencv.imgcodecs.Imgcodecs;
  19. import org.opencv.imgproc.Imgproc;
  20. import org.opencv.xfeatures2d.SURF;
  21. class SURFFLANNMatchingHomography {
  22. public void run(String[] args) {
  23. String filenameObject = args.length > 1 ? args[0] : "../data/box.png";
  24. String filenameScene = args.length > 1 ? args[1] : "../data/box_in_scene.png";
  25. Mat imgObject = Imgcodecs.imread(filenameObject, Imgcodecs.IMREAD_GRAYSCALE);
  26. Mat imgScene = Imgcodecs.imread(filenameScene, Imgcodecs.IMREAD_GRAYSCALE);
  27. if (imgObject.empty() || imgScene.empty()) {
  28. System.err.println("Cannot read images!");
  29. System.exit(0);
  30. }
  31. //-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
  32. double hessianThreshold = 400;
  33. int nOctaves = 4, nOctaveLayers = 3;
  34. boolean extended = false, upright = false;
  35. SURF detector = SURF.create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
  36. MatOfKeyPoint keypointsObject = new MatOfKeyPoint(), keypointsScene = new MatOfKeyPoint();
  37. Mat descriptorsObject = new Mat(), descriptorsScene = new Mat();
  38. detector.detectAndCompute(imgObject, new Mat(), keypointsObject, descriptorsObject);
  39. detector.detectAndCompute(imgScene, new Mat(), keypointsScene, descriptorsScene);
  40. //-- Step 2: Matching descriptor vectors with a FLANN based matcher
  41. // Since SURF is a floating-point descriptor NORM_L2 is used
  42. DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
  43. List<MatOfDMatch> knnMatches = new ArrayList<>();
  44. matcher.knnMatch(descriptorsObject, descriptorsScene, knnMatches, 2);
  45. //-- Filter matches using the Lowe's ratio test
  46. float ratioThresh = 0.75f;
  47. List<DMatch> listOfGoodMatches = new ArrayList<>();
  48. for (int i = 0; i < knnMatches.size(); i++) {
  49. if (knnMatches.get(i).rows() > 1) {
  50. DMatch[] matches = knnMatches.get(i).toArray();
  51. if (matches[0].distance < ratioThresh * matches[1].distance) {
  52. listOfGoodMatches.add(matches[0]);
  53. }
  54. }
  55. }
  56. MatOfDMatch goodMatches = new MatOfDMatch();
  57. goodMatches.fromList(listOfGoodMatches);
  58. //-- Draw matches
  59. Mat imgMatches = new Mat();
  60. Features2d.drawMatches(imgObject, keypointsObject, imgScene, keypointsScene, goodMatches, imgMatches, Scalar.all(-1),
  61. Scalar.all(-1), new MatOfByte(), Features2d.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS);
  62. //-- Localize the object
  63. List<Point> obj = new ArrayList<>();
  64. List<Point> scene = new ArrayList<>();
  65. List<KeyPoint> listOfKeypointsObject = keypointsObject.toList();
  66. List<KeyPoint> listOfKeypointsScene = keypointsScene.toList();
  67. for (int i = 0; i < listOfGoodMatches.size(); i++) {
  68. //-- Get the keypoints from the good matches
  69. obj.add(listOfKeypointsObject.get(listOfGoodMatches.get(i).queryIdx).pt);
  70. scene.add(listOfKeypointsScene.get(listOfGoodMatches.get(i).trainIdx).pt);
  71. }
  72. MatOfPoint2f objMat = new MatOfPoint2f(), sceneMat = new MatOfPoint2f();
  73. objMat.fromList(obj);
  74. sceneMat.fromList(scene);
  75. double ransacReprojThreshold = 3.0;
  76. Mat H = Calib3d.findHomography( objMat, sceneMat, Calib3d.RANSAC, ransacReprojThreshold );
  77. //-- Get the corners from the image_1 ( the object to be "detected" )
  78. Mat objCorners = new Mat(4, 1, CvType.CV_32FC2), sceneCorners = new Mat();
  79. float[] objCornersData = new float[(int) (objCorners.total() * objCorners.channels())];
  80. objCorners.get(0, 0, objCornersData);
  81. objCornersData[0] = 0;
  82. objCornersData[1] = 0;
  83. objCornersData[2] = imgObject.cols();
  84. objCornersData[3] = 0;
  85. objCornersData[4] = imgObject.cols();
  86. objCornersData[5] = imgObject.rows();
  87. objCornersData[6] = 0;
  88. objCornersData[7] = imgObject.rows();
  89. objCorners.put(0, 0, objCornersData);
  90. Core.perspectiveTransform(objCorners, sceneCorners, H);
  91. float[] sceneCornersData = new float[(int) (sceneCorners.total() * sceneCorners.channels())];
  92. sceneCorners.get(0, 0, sceneCornersData);
  93. //-- Draw lines between the corners (the mapped object in the scene - image_2 )
  94. Imgproc.line(imgMatches, new Point(sceneCornersData[0] + imgObject.cols(), sceneCornersData[1]),
  95. new Point(sceneCornersData[2] + imgObject.cols(), sceneCornersData[3]), new Scalar(0, 255, 0), 4);
  96. Imgproc.line(imgMatches, new Point(sceneCornersData[2] + imgObject.cols(), sceneCornersData[3]),
  97. new Point(sceneCornersData[4] + imgObject.cols(), sceneCornersData[5]), new Scalar(0, 255, 0), 4);
  98. Imgproc.line(imgMatches, new Point(sceneCornersData[4] + imgObject.cols(), sceneCornersData[5]),
  99. new Point(sceneCornersData[6] + imgObject.cols(), sceneCornersData[7]), new Scalar(0, 255, 0), 4);
  100. Imgproc.line(imgMatches, new Point(sceneCornersData[6] + imgObject.cols(), sceneCornersData[7]),
  101. new Point(sceneCornersData[0] + imgObject.cols(), sceneCornersData[1]), new Scalar(0, 255, 0), 4);
  102. //-- Show detected matches
  103. HighGui.imshow("Good Matches & Object detection", imgMatches);
  104. HighGui.waitKey(0);
  105. System.exit(0);
  106. }
  107. }
  108. public class SURFFLANNMatchingHomographyDemo {
  109. public static void main(String[] args) {
  110. // Load the native OpenCV library
  111. System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  112. new SURFFLANNMatchingHomography().run(args);
  113. }
  114. }