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 }