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