-
Notifications
You must be signed in to change notification settings - Fork 5
/
ImgDescriptor.java
116 lines (99 loc) · 4.21 KB
/
ImgDescriptor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package org.genericsystem.cv.application;
import java.util.ArrayList;
import java.util.List;
import org.genericsystem.cv.application.SuperFrameImg;
import org.opencv.calib3d.Calib3d;
import org.opencv.core.Core;
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.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.features2d.BFMatcher;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.FastFeatureDetector;
import org.opencv.xfeatures2d.BriefDescriptorExtractor;
public class ImgDescriptor {
private static final BriefDescriptorExtractor briefExtractor = BriefDescriptorExtractor.create(32, false);
private static final FastFeatureDetector detector = FastFeatureDetector.create(10, true, FastFeatureDetector.TYPE_9_16);
private static final DescriptorMatcher matcher = BFMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING, true);
private final SuperFrameImg superFrame;
private final MatOfKeyPoint keypoints = new MatOfKeyPoint();
private final Mat descriptors;
private final long timeStamp;
public ImgDescriptor(SuperFrameImg superFrame) {
this.superFrame = superFrame;
detector.detect(superFrame.getFrame().getSrc(), keypoints);
// keypoints = detect(deperspectivedImg);
assert keypoints != null && !keypoints.empty();
descriptors = new Mat();
briefExtractor.compute(superFrame.getFrame().getSrc(), keypoints, descriptors);
// EXTRACTOR.compute(deperspectivedImg.getSrc(), keypoints, descriptors);
timeStamp = System.currentTimeMillis();
}
public SuperFrameImg getSuperFrame() {
return superFrame;
}
public Mat getDescriptors() {
return descriptors;
}
public MatOfKeyPoint getKeypoints() {
return keypoints;
}
public long getTimeStamp(){
return timeStamp;
}
public Reconciliation computeReconciliation(ImgDescriptor reference) {
MatOfDMatch matches = new MatOfDMatch();
// System.out.println(frameDescriptor.getDescriptors());
matcher.match(getDescriptors(), reference.getDescriptors(), matches);
List<KeyPoint> referenceKeyPoints = reference.getKeypoints().toList();
List<KeyPoint> keyPoints = getKeypoints().toList();
List<Point> referencePts = new ArrayList<>();
List<Point> pts = new ArrayList<>();
for (DMatch goodMatch : matches.toArray())
if (goodMatch.distance <= 120) {
referencePts.add(referenceKeyPoints.get(goodMatch.trainIdx).pt);
pts.add(keyPoints.get(goodMatch.queryIdx).pt);
}
if (referencePts.size() > 40) {
// List<Point[]> pairedPoints = new ArrayList<>();
// for (int i = 0; i < goodNewKeypoints.size(); i++)
// pairedPoints.add(new Point[] { goodOldKeypoints.get(i), goodNewKeypoints.get(i) });
// double[] transScaleParams = new LevenbergImpl<>((points, params) -> distance(points, params), pairedPoints, new double[] { 1, 1, 0, 0 }).getParams();
// System.out.println("params " + Arrays.toString(transScaleParams));
// Mat result = getTSMat(transScaleParams);
Mat result = Calib3d.findHomography(new MatOfPoint2f(pts.stream().toArray(Point[]::new)), new MatOfPoint2f(referencePts.stream().toArray(Point[]::new)), Calib3d.RANSAC, 1);
if (result.size().empty()) {
System.out.println("Stabilization homography is empty");
return null;
}
if (!isValidHomography(result)) {
System.out.println("Not a valid homography");
return null;
}
return new Reconciliation(result, pts, referencePts);
} else {
//System.out.println("Not enough matches (" + referencePts.size() + ")");
return null;
}
}
private boolean isValidHomography(Mat homography) {
int w = superFrame.getFrame().width();
int h = superFrame.getFrame().height();
MatOfPoint2f original = new MatOfPoint2f(new Point[] { new Point(0, 0), new Point(w, 0), new Point(w, h), new Point(0, h) });
MatOfPoint2f dst = new MatOfPoint2f();
Core.perspectiveTransform(original, dst, homography);
List<Point> targets = dst.toList();
return isClockwise(targets.get(0), targets.get(1), targets.get(2));
}
private boolean isClockwise(Point a, Point b, Point c) {
double areaSum = 0;
areaSum += a.x * (b.y - c.y);
areaSum += b.x * (c.y - a.y);
areaSum += c.x * (a.y - b.y);
return areaSum > 0;
}
}