1 /*
2 Copyright (c) 2019 Ferhat Kurtulmuş
3 Boost Software License - Version 1.0 - August 17th, 2003
4 Permission is hereby granted, free of charge, to any person or organization
5 obtaining a copy of the software and accompanying documentation covered by
6 this license (the "Software") to use, reproduce, display, distribute,
7 execute, and transmit the Software, and to prepare derivative works of the
8 Software, and to permit third-parties to whom the Software is furnished to
9 do so, all subject to the following:
10 The copyright notices in the Software and this entire statement, including
11 the above license grant, this restriction and the following disclaimer,
12 must be included in all copies of the Software, in whole or in part, and
13 all derivative works of the Software, unless such copies or derivative
14 works are solely in the form of machine-executable object code generated by
15 a source language processor.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
19 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
20 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24 
25 module opencvd.features2d;
26 
27 import std.conv;
28 
29 import opencvd.cvcore;
30 
31 private extern (C){
32     AKAZE AKAZE_Create();
33     void AKAZE_Close(AKAZE a);
34     KeyPoints AKAZE_Detect(AKAZE a, Mat src);
35     KeyPoints AKAZE_DetectAndCompute(AKAZE a, Mat src, Mat mask, Mat desc);
36     
37     AgastFeatureDetector AgastFeatureDetector_Create();
38     void AgastFeatureDetector_Close(AgastFeatureDetector a);
39     KeyPoints AgastFeatureDetector_Detect(AgastFeatureDetector a, Mat src);
40 
41     BRISK BRISK_Create();
42     void BRISK_Close(BRISK b);
43     KeyPoints BRISK_Detect(BRISK b, Mat src);
44     KeyPoints BRISK_DetectAndCompute(BRISK b, Mat src, Mat mask, Mat desc);
45 
46     FastFeatureDetector FastFeatureDetector_Create();
47     void FastFeatureDetector_Close(FastFeatureDetector f);
48     KeyPoints FastFeatureDetector_Detect(FastFeatureDetector f, Mat src);
49 
50     GFTTDetector GFTTDetector_Create();
51     void GFTTDetector_Close(GFTTDetector a);
52     KeyPoints GFTTDetector_Detect(GFTTDetector a, Mat src);
53 
54     KAZE KAZE_Create();
55     void KAZE_Close(KAZE a);
56     KeyPoints KAZE_Detect(KAZE a, Mat src);
57     KeyPoints KAZE_DetectAndCompute(KAZE a, Mat src, Mat mask, Mat desc);
58 
59     MSER MSER_Create();
60     void MSER_Close(MSER a);
61     KeyPoints MSER_Detect(MSER a, Mat src);
62 
63     ORB ORB_Create();
64     void ORB_Close(ORB o);
65     KeyPoints ORB_Detect(ORB o, Mat src);
66     KeyPoints ORB_DetectAndCompute(ORB o, Mat src, Mat mask, Mat desc);
67 
68     SimpleBlobDetector SimpleBlobDetector_Create();
69     void SimpleBlobDetector_Close(SimpleBlobDetector b);
70     KeyPoints SimpleBlobDetector_Detect(SimpleBlobDetector b, Mat src);
71 
72     BFMatcher BFMatcher_Create();
73     BFMatcher BFMatcher_CreateWithParams(int normType, bool crossCheck);
74     void BFMatcher_Close(BFMatcher b);
75     MultiDMatches BFMatcher_KnnMatch(BFMatcher b, Mat query, Mat train, int k);
76 
77     void DrawKeyPoints(Mat src, KeyPoints kp, Mat dst, const Scalar s, int flags);
78     
79     FlannBasedMatcher FlannBasedMatcher_Create1();
80     void FlannBasedMatcher_Close(FlannBasedMatcher fbm);
81     MultiDMatches FlannBasedMatcher_KnnMatch(FlannBasedMatcher fbm,
82         Mat queryDescriptors, Mat trainDescriptors, int k, Mat mask, bool compactResult);
83     void DrawMatches1(Mat img1,
84                 KeyPoints kp1,
85                 Mat img2,
86                 KeyPoints kp2,
87                 DMatches matches1to2,
88                 Mat outImg,
89                 Scalar matchColor,
90                 Scalar singlePointColor,
91                 CharVector matchesMask,
92                 int flags);
93 }
94 
95 struct AKAZE {
96     void* p;
97     
98     static AKAZE opCall(){
99         return AKAZE_Create();
100     }
101     
102     KeyPoint[] detect(Mat src){
103         KeyPoints kpts = AKAZE_Detect(this, src);
104         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
105         KeyPoints_Close(kpts);
106         return ret;
107     }
108     
109     KeyPoint[] detectAndCompute(Mat src, Mat mask, Mat desc){
110         KeyPoints kpts = AKAZE_DetectAndCompute(this, src, mask, desc);
111         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
112         KeyPoints_Close(kpts);
113         return ret;
114     }
115 }
116 
117 void Destroy(AKAZE a){
118     AKAZE_Close(a);
119 }
120 
121 struct AgastFeatureDetector{
122     void* p;
123     
124     static AgastFeatureDetector opCall(){
125         return AgastFeatureDetector_Create();
126     }
127     
128     KeyPoint[] detect(Mat src){
129         KeyPoints kpts = AgastFeatureDetector_Detect(this, src);
130         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
131         KeyPoints_Close(kpts);
132         return ret;
133     }
134 }
135 
136 void Destroy(AgastFeatureDetector a){
137     AgastFeatureDetector_Close(a);
138 }
139 
140 struct BRISK {
141     void* p;
142     
143     static BRISK opCall(){
144         return BRISK_Create();
145     }
146     
147     KeyPoint[] detect(Mat src){
148         KeyPoints kpts = BRISK_Detect(this, src);
149         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
150         KeyPoints_Close(kpts);
151         return ret;
152     }
153     
154     KeyPoint[] detectAndCompute(Mat src, Mat mask, Mat desc){
155         KeyPoints kpts = BRISK_DetectAndCompute(this, src, mask, desc);
156         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
157         KeyPoints_Close(kpts);
158         return ret;
159     }
160 }
161 
162 void Destroy(BRISK a){
163     BRISK_Close(a);
164 }
165 
166 struct FastFeatureDetector {
167     void* p;
168     
169     static FastFeatureDetector opCall(){
170         return FastFeatureDetector_Create();
171     }
172     
173     KeyPoint[] detect(Mat src){
174         KeyPoints kpts = FastFeatureDetector_Detect(this, src);
175         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
176         KeyPoints_Close(kpts);
177         return ret;
178     }
179 }
180 
181 void Destroy(FastFeatureDetector a){
182     FastFeatureDetector_Close(a);
183 }
184 
185 struct GFTTDetector {
186     void* p;
187     
188     static GFTTDetector opCall(){
189         return GFTTDetector_Create();
190     }
191     
192     KeyPoint[] detect(Mat src){
193         KeyPoints kpts = GFTTDetector_Detect(this, src);
194         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
195         KeyPoints_Close(kpts);
196         return ret;
197     }
198 }
199 
200 void Destroy(GFTTDetector a){
201     GFTTDetector_Close(a);
202 }
203 
204 struct KAZE {
205     void* p;
206     
207     static KAZE opCall(){
208         return KAZE_Create();
209     }
210     
211     KeyPoint[] detect(Mat src){
212         KeyPoints kpts = KAZE_Detect(this, src);
213         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
214         KeyPoints_Close(kpts);
215         return ret;
216     }
217     
218     KeyPoint[] detectAndCompute(Mat src, Mat mask, Mat desc){
219         KeyPoints kpts = KAZE_DetectAndCompute(this, src, mask, desc);
220         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
221         KeyPoints_Close(kpts);
222         return ret;
223     }
224 }
225 
226 void Destroy(KAZE a){
227     KAZE_Close(a);
228 }
229 
230 struct MSER {
231     void* p;
232     
233     static MSER opCall(){
234         return MSER_Create();
235     }
236     
237     KeyPoint[] detect(Mat src){
238         KeyPoints kpts = MSER_Detect(this, src);
239         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
240         KeyPoints_Close(kpts);
241         return ret;
242     }
243 }
244 void Destroy(MSER a){
245     MSER_Close(a);
246 }
247 
248 struct ORB {
249     void* p;
250     
251     static ORB opCall(){
252         return ORB_Create();
253     }
254     
255     KeyPoint[] detect(Mat src){
256         KeyPoints kpts = ORB_Detect(this, src);
257         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
258         KeyPoints_Close(kpts);
259         return ret;
260     }
261     
262     KeyPoint[] detectAndCompute(Mat src, Mat mask, Mat desc){
263         KeyPoints kpts = ORB_DetectAndCompute(this, src, mask, desc);
264         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
265         KeyPoints_Close(kpts);
266         return ret;
267     }
268 }
269 
270 void Destroy(ORB a){
271     ORB_Close(a);
272 }
273 
274 struct SimpleBlobDetector {
275     void* p;
276     
277     static SimpleBlobDetector opCall(){
278         return SimpleBlobDetector_Create();
279     }
280     
281     KeyPoint[] detect(Mat src){
282         KeyPoints kpts = SimpleBlobDetector_Detect(this, src);
283         KeyPoint[] ret = kpts.keypoints[0..kpts.length].dup;
284         KeyPoints_Close(kpts);
285         return ret;
286     }
287 }
288 
289 void Destroy(SimpleBlobDetector a){
290     SimpleBlobDetector_Close(a);
291 }
292 
293 struct BFMatcher {
294     void* p;
295     /*
296     static BFMatcher opCall(){
297         return BFMatcher_Create();
298     }
299     */
300     static BFMatcher opCall(int normType=NORM_L2, bool crossCheck=false){
301         return BFMatcher_CreateWithParams(normType, crossCheck);
302     }
303     
304     DMatch[][] knnMatch(Mat query, Mat train, int k){
305         
306         MultiDMatches mdms = BFMatcher_KnnMatch(this, query, train, k);
307         
308         DMatch[][] ret; ret.length = mdms.length;
309         foreach(i; 0..mdms.length){
310             DMatches ds = mdms.dmatches[i];
311             DMatch[] dmats = ds.dmatches[0..ds.length].dup;
312             ret[i] = dmats;
313         }
314         MultiDMatches_Close(mdms);
315         return ret;
316     }
317 }
318 
319 void Destroy(BFMatcher a){
320     BFMatcher_Close(a);
321 }
322 
323 enum: int { // cv::DrawMatchesFlags 
324     DrawMatchesFlags_DEFAULT = 0, 
325     DrawMatchesFlags_DRAW_OVER_OUTIMG = 1, 
326     DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS = 2, 
327     DrawMatchesFlags_DRAW_RICH_KEYPOINTS = 4 
328 }
329 
330 void drawKeyPoints(Mat src, KeyPoint[] kp, Mat dst,
331         const Scalar s = Scalar.all(-1), int flags = DrawMatchesFlags_DEFAULT){
332     DrawKeyPoints(src, KeyPoints(kp.ptr, kp.length.to!int), dst, s, flags);
333 }
334 
335 struct FlannBasedMatcher {
336     void* p;
337     
338     static FlannBasedMatcher opCall(){
339         return FlannBasedMatcher_Create1();
340     }
341     
342     DMatch[][] knnMatch(
343         Mat queryDescriptors, Mat trainDescriptors, int k, Mat mask = Mat(), bool compactResult=false){
344         
345         MultiDMatches mdms = FlannBasedMatcher_KnnMatch(this, queryDescriptors, trainDescriptors, k, mask, compactResult);
346         
347         DMatch[][] ret; ret.length = mdms.length;
348         foreach(i; 0..mdms.length){
349             DMatches ds = mdms.dmatches[i];
350             DMatch[] dmats = ds.dmatches[0..ds.length].dup;
351             ret[i] = dmats;
352         }
353         MultiDMatches_Close(mdms);
354         return ret;
355     }
356 }
357 
358 void Destroy(FlannBasedMatcher fbm){
359     FlannBasedMatcher_Close(fbm);
360 }
361 
362 void drawMatches(Mat img1,
363                 KeyPoint[] kp1,
364                 Mat img2,
365                 KeyPoint[] kp2,
366                 DMatch[] matches1to2,
367                 Mat outImg,
368                 Scalar matchColor = Scalar.all(-1),
369                 Scalar singlePointColor = Scalar.all(-1),
370                 char[] matchesMask = [],
371                 int flags = DrawMatchesFlags_DEFAULT){
372     DrawMatches1(img1,
373                 KeyPoints(kp1.ptr, kp1.length.to!int),
374                 img2,
375                 KeyPoints(kp2.ptr, kp2.length.to!int),
376                 DMatches(matches1to2.ptr, matches1to2.length.to!int),
377                 outImg,
378                 matchColor,
379                 singlePointColor,
380                 CharVector(matchesMask.ptr, matchesMask.length.to!int),
381                 flags);
382 }