Detect, Compute, and Match Descriptors
This program demonstrates how to detect, compute, and match descriptors using various algorithms: ORB, BRISK, and AKAZE.
Sources:
load a pair of grayscale images
img1 = cv.imread(fullfile(mexopencv.root(),'test','basketball1.png'), 'Grayscale',true); img2 = cv.imread(fullfile(mexopencv.root(),'test','basketball2.png'), 'Grayscale',true);
descriptors we are going to detect and compute
features = {'AKAZEUpright', 'AKAZE', 'KAZE', 'ORB', 'BRISK'}; if true features = [features, 'SIFT', 'SURF']; % xfeatures2d from opencv_contrib end
algorithms used to match descriptors
matchers = strcat('BruteForce', {'', '-L1', '-Hamming', '-Hamming(2)'});
descriptors loop
D = nan(numel(features), numel(matchers)); for i=1:numel(features) % create Feature2D object switch features{i} case 'AKAZEUpright' b = cv.AKAZE('DescriptorType','KAZEUpright'); case 'AKAZE' b = cv.AKAZE(); case 'KAZE' b = cv.KAZE(); case 'ORB' b = cv.ORB(); case 'BRISK' b = cv.BRISK(); case 'SIFT' b = cv.SIFT(); case 'SURF' b = cv.SURF(); end % detect and compute descriptors in both images [kpts1, desc1] = b.detectAndCompute(img1); [kpts2, desc2] = b.detectAndCompute(img2); % matchers loop for j=1:numel(matchers) % create DescriptorMatcher object m = cv.DescriptorMatcher(matchers{j}); % warn about invalid combinations of descriptors and matchers valid = true; mHam = ~isempty(strfind(matchers{j}, 'Hamming')); bHam = ~isempty(strfind(b.defaultNorm(), 'Hamming')); if mHam && (~bHam || strcmp(b.descriptorType, 'single')) fprintf(2, 'Hamming distance only for binary descriptors\n'); if mexopencv.isOctave() %HACK: avoid unhandled C++ expections, they can crash Octave! valid = false; end end if ~mHam && bHam fprintf(2, 'L1 or L2 distance not for binary descriptors\n'); end fprintf('%s + %s:\n', features{i}, matchers{j}); fprintf(' %d keypoints in img1\n', numel(kpts1)); fprintf(' %d keypoints in img2\n', numel(kpts2)); try % match descriptors assert(valid); matches = m.match(desc1, desc2); fprintf(' %d matches\n', numel(matches)); % save matches to file fname = sprintf('%s_%s.yml', features{i}, matchers{j}); fname = fullfile(tempdir(), fname); cv.FileStorage(fname, struct('Matches',matches)); % Keep only best 30 matches to have a nice drawing (sorted by dist) [~,ord] = sort([matches.distance]); ord(31:end) = []; matches = matches(ord); % pretty print matches if ~mexopencv.isOctave() t = struct2table(matches); t.imgIdx = []; display(t) else %HACK: no tables in Octave t = cat(1, matches.distance); display(t) end % draw matches and show result out = cv.drawMatches(img1, kpts1, img2, kpts2, matches); figure, imshow(out) title(sprintf('%s + %s', features{i}, matchers{j})) % compute total distances between keypoint matches pts1 = cat(1, kpts1([matches.queryIdx]+1).pt); pts2 = cat(1, kpts2([matches.trainIdx]+1).pt); D(i,j) = sum(sqrt(sum((pts1 - pts2).^2, 2))); fprintf(' %f total error\n', D(i,j)); catch ME fprintf(' matching failed\n'); %warning(getReport(ME)) end fprintf('%s\n', repmat('-',1,80)); end end
AKAZEUpright + BruteForce: 509 keypoints in img1 489 keypoints in img2 509 matches t = 30×3 table queryIdx trainIdx distance ________ ________ _________ 225 212 0.0061414 425 400 0.0065284 228 216 0.0078475 432 407 0.0078775 285 270 0.0089423 259 244 0.0089759 413 388 0.0093736 1 0 0.009867 286 272 0.0099593 105 91 0.010512 115 102 0.010668 486 464 0.010733 287 273 0.011009 233 219 0.011101 3 1 0.011432 108 94 0.012 291 277 0.012291 288 274 0.01242 246 231 0.012453 6 4 0.013142 276 262 0.015391 114 100 0.015577 112 97 0.016037 273 261 0.016045 121 108 0.016096 4 2 0.016369 294 279 0.016634 292 276 0.017646 111 98 0.017932 110 96 0.018505 76.347928 total error -------------------------------------------------------------------------------- AKAZEUpright + BruteForce-L1: 509 keypoints in img1 489 keypoints in img2 509 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 225 212 0.035796 425 400 0.039139 432 407 0.045195 228 216 0.047979 286 272 0.04935 259 244 0.052619 285 270 0.052759 413 388 0.055712 1 0 0.056515 486 464 0.060291 105 91 0.060574 115 102 0.061157 3 1 0.06201 288 274 0.065543 233 219 0.065866 291 277 0.065992 287 273 0.067931 108 94 0.07174 246 231 0.07656 6 4 0.078552 276 262 0.079296 112 97 0.091108 273 261 0.091113 114 100 0.091542 294 279 0.092278 398 376 0.092863 4 2 0.092881 121 108 0.093999 292 276 0.094359 111 98 0.097353 75.509662 total error -------------------------------------------------------------------------------- Hamming distance only for binary descriptors AKAZEUpright + BruteForce-Hamming: 509 keypoints in img1 489 keypoints in img2 matching failed -------------------------------------------------------------------------------- Hamming distance only for binary descriptors AKAZEUpright + BruteForce-Hamming(2): 509 keypoints in img1 489 keypoints in img2 matching failed -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors AKAZE + BruteForce: 589 keypoints in img1 569 keypoints in img2 589 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 444 421 0 461 438 2 432 411 5.6569 310 296 8.2462 318 302 8.3666 39 25 8.4853 439 416 12.042 42 31 14.595 275 262 16.031 316 300 17.205 312 298 17.889 225 215 23.431 265 254 23.685 135 123 29.086 469 445 32.016 125 113 32.062 127 115 37.736 44 34 42.544 542 517 43.543 309 294 48.052 167 155 62.137 255 243 65.315 315 301 68.066 122 108 72.166 249 237 74.135 448 424 75.472 153 145 93.145 535 507 94.366 547 524 96 537 510 99.479 77.536100 total error -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors AKAZE + BruteForce-L1: 589 keypoints in img1 569 keypoints in img2 589 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 444 421 0 461 438 2 432 411 8 310 296 10 39 25 12 318 302 12 275 262 17 439 416 21 312 298 24 316 300 28 42 31 31 469 445 33 125 113 34 225 215 43 265 254 45 309 294 51 127 115 68 135 123 80 44 34 86 542 517 100 448 424 104 315 301 105 122 108 112 249 237 128 118 105 146 167 155 151 547 524 160 535 507 169 131 119 173 295 106 180 80.196240 total error -------------------------------------------------------------------------------- AKAZE + BruteForce-Hamming: 589 keypoints in img1 569 keypoints in img2 589 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 444 421 0 461 438 1 125 113 2 275 262 2 310 296 2 312 298 2 432 411 2 469 445 2 39 25 3 118 105 3 305 291 3 547 524 3 115 102 4 137 127 4 309 294 4 318 302 4 325 310 4 439 416 4 448 424 4 127 115 5 131 119 5 316 300 5 21 15 6 42 31 6 122 108 6 225 215 6 265 254 6 295 106 6 311 297 6 11 5 7 103.266482 total error -------------------------------------------------------------------------------- AKAZE + BruteForce-Hamming(2): 589 keypoints in img1 569 keypoints in img2 589 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 444 421 0 461 438 1 125 113 2 275 262 2 310 296 2 312 298 2 432 411 2 469 445 2 39 25 3 118 105 3 305 291 3 309 294 3 547 524 3 115 102 4 137 127 4 318 302 4 325 310 4 439 416 4 448 424 4 127 115 5 131 119 5 316 300 5 21 15 6 42 31 6 122 108 6 225 215 6 265 254 6 295 106 6 311 297 6 11 5 7 103.266482 total error -------------------------------------------------------------------------------- KAZE + BruteForce: 962 keypoints in img1 909 keypoints in img2 962 matches t = 30×3 table queryIdx trainIdx distance ________ ________ _________ 405 388 0.0085198 646 621 0.0088553 457 432 0.0093376 18 16 0.0096003 208 193 0.010034 449 425 0.010102 187 176 0.010281 511 480 0.01029 2 1 0.010337 216 202 0.010546 131 123 0.011074 818 764 0.011187 149 142 0.011195 0 0 0.011843 389 370 0.012087 191 179 0.012396 207 191 0.013254 196 183 0.013399 144 138 0.014298 14 12 0.014497 634 610 0.014566 454 429 0.016669 204 188 0.01698 96 84 0.020786 220 206 0.021669 145 139 0.021678 921 863 0.021951 532 502 0.023943 19 17 0.024116 447 423 0.024717 50.046663 total error -------------------------------------------------------------------------------- KAZE + BruteForce-L1: 962 keypoints in img1 909 keypoints in img2 962 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 449 425 0.046328 457 432 0.050101 405 388 0.052212 646 621 0.053055 2 1 0.055326 18 16 0.056384 0 0 0.057026 818 764 0.057264 208 193 0.057709 187 176 0.057777 511 480 0.058332 216 202 0.058883 149 142 0.061423 131 123 0.068747 389 370 0.071617 191 179 0.075301 634 610 0.080895 196 183 0.082588 207 191 0.084627 204 188 0.086547 14 12 0.090572 144 138 0.093892 96 84 0.099536 454 429 0.10454 220 206 0.11729 145 139 0.12303 921 863 0.12421 536 505 0.13232 532 502 0.13498 19 17 0.13511 50.707891 total error -------------------------------------------------------------------------------- Hamming distance only for binary descriptors KAZE + BruteForce-Hamming: 962 keypoints in img1 909 keypoints in img2 matching failed -------------------------------------------------------------------------------- Hamming distance only for binary descriptors KAZE + BruteForce-Hamming(2): 962 keypoints in img1 909 keypoints in img2 matching failed -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors ORB + BruteForce: 500 keypoints in img1 500 keypoints in img2 500 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 2 98 11.314 192 173 34.176 80 61 46.54 77 7 51.769 81 90 57.991 247 221 65.276 174 122 66.091 137 139 72.076 149 151 73.607 206 237 73.79 319 316 73.844 13 75 80.144 199 225 84.06 392 392 95.682 252 236 97.432 368 341 97.499 60 8 101.18 249 278 105.33 345 369 107.87 166 146 109.8 124 120 112.03 357 363 118.08 351 346 120.96 216 356 125.39 46 97 129.22 115 144 130.32 123 114 132.79 71 40 133.2 163 147 134.42 193 155 134.6 78.299105 total error -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors ORB + BruteForce-L1: 500 keypoints in img1 500 keypoints in img2 500 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 2 98 16 192 173 52 247 221 83 174 122 84 80 61 88 137 139 111 77 7 120 149 151 122 206 237 123 81 90 145 319 316 147 13 75 153 46 97 157 115 144 173 71 40 191 123 114 194 223 244 198 345 369 203 175 166 210 99 104 213 163 147 216 60 8 218 199 225 218 392 392 219 193 155 220 351 346 220 211 249 223 35 68 232 272 272 236 124 120 237 70.072139 total error -------------------------------------------------------------------------------- ORB + BruteForce-Hamming: 500 keypoints in img1 500 keypoints in img2 500 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 2 98 2 174 122 3 192 173 4 247 221 5 46 97 6 99 104 6 223 244 6 149 151 7 206 237 7 71 40 8 136 138 8 137 139 8 1 3 9 13 75 9 35 68 9 80 61 9 115 144 9 345 369 9 351 346 9 358 355 9 394 419 9 22 92 10 77 7 10 123 114 10 147 129 10 163 147 10 211 249 10 272 272 10 339 371 10 374 340 10 48.577527 total error -------------------------------------------------------------------------------- ORB + BruteForce-Hamming(2): 500 keypoints in img1 500 keypoints in img2 500 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 2 98 2 174 122 3 192 173 4 247 221 5 46 97 6 99 104 6 223 244 6 149 151 7 206 237 7 71 40 8 115 144 8 136 138 8 137 139 8 1 3 9 13 75 9 22 92 9 35 68 9 80 61 9 123 114 9 345 369 9 351 346 9 358 355 9 394 419 9 77 7 10 147 129 10 163 147 10 211 249 10 272 272 10 295 276 10 339 371 10 50.305524 total error -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors BRISK + BruteForce: 767 keypoints in img1 735 keypoints in img2 767 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 433 418 30.594 523 505 32 401 383 33.956 664 637 64.031 224 217 75.266 185 178 75.286 413 395 78.39 648 621 80.623 357 331 84.581 0 0 90.708 673 555 92.027 549 637 92.26 14 14 113.82 153 144 119.92 655 628 120.09 374 348 128.09 277 271 133.6 41 38 135.1 272 404 136.87 361 336 139.23 646 619 143.11 204 196 146.64 423 410 146.87 270 266 148.03 574 555 149.63 402 384 153.21 638 614 158.52 576 559 159.86 418 265 160.02 172 163 160.55 60.398485 total error -------------------------------------------------------------------------------- L1 or L2 distance not for binary descriptors BRISK + BruteForce-L1: 767 keypoints in img1 735 keypoints in img2 767 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 523 505 32 401 383 49 664 637 66 433 418 68 413 395 129 374 348 136 224 217 137 0 0 138 185 178 140 673 555 151 549 637 152 648 621 162 646 619 192 277 271 204 357 331 214 204 196 224 423 410 234 361 336 253 272 404 255 270 266 266 153 144 292 206 197 313 172 163 316 14 14 318 402 384 325 638 614 325 3 5 327 574 555 331 643 618 337 576 559 338 49.992817 total error -------------------------------------------------------------------------------- BRISK + BruteForce-Hamming: 767 keypoints in img1 735 keypoints in img2 767 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 523 505 1 646 619 2 664 637 2 204 196 3 374 348 4 401 383 4 413 395 4 549 637 4 0 0 5 423 410 5 96 87 6 673 555 6 167 157 7 224 217 7 433 418 8 648 621 8 172 163 9 185 178 10 315 295 10 724 696 10 411 393 11 3 5 12 270 266 12 277 271 12 361 336 12 402 384 12 420 406 12 89 82 13 197 189 13 731 704 13 56.118373 total error -------------------------------------------------------------------------------- BRISK + BruteForce-Hamming(2): 767 keypoints in img1 735 keypoints in img2 767 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 523 505 1 646 619 2 664 637 2 204 196 3 374 348 4 401 383 4 413 395 4 549 637 4 0 0 5 423 410 5 96 87 6 167 157 6 673 555 6 224 217 7 433 418 8 648 621 8 172 163 9 185 178 10 315 295 10 411 393 10 724 696 10 402 384 11 3 5 12 270 266 12 277 271 12 361 336 12 420 406 12 89 82 13 197 189 13 377 521 13 56.575280 total error -------------------------------------------------------------------------------- SIFT + BruteForce: 538 keypoints in img1 554 keypoints in img2 538 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 151 158 7.6158 200 206 9.434 169 183 9.8995 133 138 10.05 122 126 11.18 145 152 12.124 135 140 12.806 180 192 13.304 128 131 13.342 154 165 14.107 189 198 14.248 153 162 17.117 138 143 17.378 137 142 17.578 14 13 17.972 76 77 19.209 181 193 20.224 85 91 21.237 20 20 21.307 129 133 21.794 110 117 21.932 107 114 22.226 440 451 22.383 162 172 22.583 164 175 23.937 163 174 24.678 81 88 24.839 171 184 25 38 37 27.129 288 308 27.532 22.399791 total error -------------------------------------------------------------------------------- SIFT + BruteForce-L1: 538 keypoints in img1 554 keypoints in img2 538 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 151 158 38 200 206 51 133 138 59 145 152 59 135 140 64 169 183 64 122 126 67 180 192 73 154 165 75 128 131 78 137 142 89 138 143 92 189 198 93 76 77 95 153 162 95 129 133 105 14 13 109 81 88 117 85 91 117 181 193 125 162 172 130 164 175 141 440 451 145 182 194 147 184 196 147 20 20 150 82 89 153 171 184 153 288 308 154 163 174 155 21.775604 total error -------------------------------------------------------------------------------- Hamming distance only for binary descriptors SIFT + BruteForce-Hamming: 538 keypoints in img1 554 keypoints in img2 matching failed -------------------------------------------------------------------------------- Hamming distance only for binary descriptors SIFT + BruteForce-Hamming(2): 538 keypoints in img1 554 keypoints in img2 matching failed -------------------------------------------------------------------------------- SURF + BruteForce: 833 keypoints in img1 819 keypoints in img2 833 matches t = 30×3 table queryIdx trainIdx distance ________ ________ _________ 21 22 0.0044549 25 26 0.0075029 741 752 0.0083626 332 324 0.0084082 371 351 0.0086561 265 248 0.0094784 129 123 0.0098364 119 112 0.010511 20 17 0.01079 104 100 0.011485 434 393 0.011719 87 93 0.011821 224 211 0.012183 72 65 0.013086 814 740 0.01342 171 165 0.013746 508 487 0.01501 380 356 0.01558 731 712 0.015842 69 68 0.015907 500 446 0.016303 502 473 0.016388 753 729 0.016895 61 67 0.017205 559 531 0.01759 663 633 0.017897 793 769 0.017943 560 475 0.018021 509 483 0.018098 403 377 0.018622 39.197591 total error -------------------------------------------------------------------------------- SURF + BruteForce-L1: 833 keypoints in img1 819 keypoints in img2 833 matches t = 30×3 table queryIdx trainIdx distance ________ ________ ________ 21 22 0.017737 25 26 0.031595 332 324 0.036884 265 248 0.039954 371 351 0.042173 129 123 0.043942 741 752 0.045758 104 100 0.049184 119 112 0.04946 434 393 0.0545 72 65 0.054785 87 93 0.054964 224 211 0.056004 20 17 0.05609 380 356 0.06616 171 165 0.066818 69 68 0.067284 814 740 0.067873 508 487 0.069274 500 446 0.071465 731 712 0.075041 61 67 0.079448 481 424 0.079876 502 473 0.081175 793 769 0.081626 247 234 0.084103 403 377 0.084347 559 531 0.084814 666 639 0.086527 535 508 0.087287 30.480832 total error -------------------------------------------------------------------------------- Hamming distance only for binary descriptors SURF + BruteForce-Hamming: 833 keypoints in img1 819 keypoints in img2 matching failed -------------------------------------------------------------------------------- Hamming distance only for binary descriptors SURF + BruteForce-Hamming(2): 833 keypoints in img1 819 keypoints in img2 matching failed --------------------------------------------------------------------------------
Cumulative distances between matched keypoint for different matchers and feature detectors
if ~mexopencv.isOctave() t = array2table(D, 'RowNames',features, ... 'VariableNames',regexprep(matchers,'\W','')); display(t) else %HACK: no tables in Octave display(D) end
t = 7×4 table BruteForce BruteForceL1 BruteForceHamming BruteForceHamming2 __________ ____________ _________________ __________________ AKAZEUpright 76.348 75.51 NaN NaN AKAZE 77.536 80.196 103.27 103.27 KAZE 50.047 50.708 NaN NaN ORB 78.299 70.072 48.578 50.306 BRISK 60.398 49.993 56.118 56.575 SIFT 22.4 21.776 NaN NaN SURF 39.198 30.481 NaN NaN