2015-05-03 17:42:27 +08:00
# include <opencv2/opencv.hpp>
# include <vector>
# include <iostream>
using namespace std ;
using namespace cv ;
2015-05-04 16:36:24 +08:00
static void help ( )
{
cout < < " \n This program demonstrates how to detect compute and match ORB BRISK and AKAZE descriptors \n "
" Usage: \n "
" ./matchmethod_orb_akaze_brisk <image1(../data/basketball1.png as default)> <image2(../data/basketball2.png as default)> \n "
" Press a key when image window is active to change algorithm or descriptor " ;
}
2015-05-03 17:42:27 +08:00
2015-05-04 16:36:24 +08:00
int main ( int argc , char * argv [ ] )
2015-05-03 17:42:27 +08:00
{
2015-05-04 16:36:24 +08:00
vector < String > typeDesc ;
2015-05-03 17:42:27 +08:00
vector < String > typeAlgoMatch ;
2015-05-04 16:36:24 +08:00
vector < String > fileName ;
help ( ) ;
2015-05-07 01:55:16 +08:00
system ( " cd " ) ;
2015-05-04 16:59:43 +08:00
// This descriptor are going to be detect and compute
2015-05-04 16:36:24 +08:00
typeDesc . push_back ( " AKAZE " ) ; // see http://docs.opencv.org/trunk/d8/d30/classcv_1_1AKAZE.html
typeDesc . push_back ( " ORB " ) ; // see http://docs.opencv.org/trunk/de/dbf/classcv_1_1BRISK.html
typeDesc . push_back ( " BRISK " ) ; // see http://docs.opencv.org/trunk/db/d95/classcv_1_1ORB.html
// This algorithm would be used to match descriptors see http://docs.opencv.org/trunk/db/d39/classcv_1_1DescriptorMatcher.html#ab5dc5036569ecc8d47565007fa518257
2015-05-03 17:42:27 +08:00
typeAlgoMatch . push_back ( " BruteForce " ) ;
2015-05-04 16:36:24 +08:00
typeAlgoMatch . push_back ( " BruteForce-L1 " ) ;
2015-05-03 17:42:27 +08:00
typeAlgoMatch . push_back ( " BruteForce-Hamming " ) ;
typeAlgoMatch . push_back ( " BruteForce-Hamming(2) " ) ;
2015-05-04 16:36:24 +08:00
if ( argc = = 1 )
{
fileName . push_back ( " ../data/basketball1.png " ) ;
fileName . push_back ( " ../data/basketball2.png " ) ;
}
else if ( argc = = 3 )
{
fileName . push_back ( argv [ 1 ] ) ;
fileName . push_back ( argv [ 2 ] ) ;
}
else
{
help ( ) ;
return ( 0 ) ;
}
Mat img1 = imread ( fileName [ 0 ] , IMREAD_GRAYSCALE ) ;
Mat img2 = imread ( fileName [ 1 ] , IMREAD_GRAYSCALE ) ;
if ( img1 . rows * img1 . cols < = 0 )
{
cout < < " Image " < < fileName [ 0 ] < < " is empty or cannot be found \n " ;
return ( 0 ) ;
}
if ( img2 . rows * img2 . cols < = 0 )
{
cout < < " Image " < < fileName [ 1 ] < < " is empty or cannot be found \n " ;
return ( 0 ) ;
}
2015-05-03 17:58:32 +08:00
2015-05-04 16:36:24 +08:00
vector < double > desMethCmp ;
2015-05-03 17:42:27 +08:00
Ptr < Feature2D > b ;
2015-05-04 16:36:24 +08:00
// Descriptor loop
2015-05-03 17:42:27 +08:00
vector < String > : : iterator itDesc ;
2015-05-04 16:36:24 +08:00
for ( itDesc = typeDesc . begin ( ) ; itDesc ! = typeDesc . end ( ) ; itDesc + + )
{
2015-05-03 17:42:27 +08:00
Ptr < DescriptorMatcher > descriptorMatcher ;
2015-05-04 16:36:24 +08:00
// Match between img1 and img2
2015-05-04 16:59:43 +08:00
vector < DMatch > matches ;
// keypoint for img1 and img2
2015-05-04 16:36:24 +08:00
vector < KeyPoint > keyImg1 , keyImg2 ;
2015-05-04 16:59:43 +08:00
// Descriptor for img1 and img2
Mat descImg1 , descImg2 ;
2015-05-03 17:42:27 +08:00
vector < String > : : iterator itMatcher = typeAlgoMatch . end ( ) ;
if ( * itDesc = = " AKAZE " ) {
b = AKAZE : : create ( ) ;
}
if ( * itDesc = = " ORB " ) {
b = ORB : : create ( ) ;
}
else if ( * itDesc = = " BRISK " ) {
b = BRISK : : create ( ) ;
}
try {
2015-05-04 16:36:24 +08:00
// We can detect keypoint with detect method
2015-05-03 17:42:27 +08:00
b - > detect ( img1 , keyImg1 , Mat ( ) ) ;
2015-05-04 16:36:24 +08:00
// and compute their descriptors with method compute
2015-05-03 17:42:27 +08:00
b - > compute ( img1 , keyImg1 , descImg1 ) ;
2015-05-04 16:36:24 +08:00
// or detect and compute descriptors in one step
2015-05-03 17:42:27 +08:00
b - > detectAndCompute ( img2 , Mat ( ) , keyImg2 , descImg2 , false ) ;
2015-05-04 16:36:24 +08:00
// Match method loop
for ( itMatcher = typeAlgoMatch . begin ( ) ; itMatcher ! = typeAlgoMatch . end ( ) ; itMatcher + + ) {
2015-05-03 17:42:27 +08:00
descriptorMatcher = DescriptorMatcher : : create ( * itMatcher ) ;
descriptorMatcher - > match ( descImg1 , descImg2 , matches , Mat ( ) ) ;
2015-05-04 16:36:24 +08:00
// Keep best matches only to have a nice drawing.
// We sort distance between descriptor matches
2015-05-03 17:42:27 +08:00
Mat index ;
2015-05-03 20:08:24 +08:00
int nbMatch = int ( matches . size ( ) ) ;
Mat tab ( nbMatch , 1 , CV_32F ) ;
for ( int i = 0 ; i < nbMatch ; i + + )
2015-05-04 16:36:24 +08:00
{
2015-05-03 17:42:27 +08:00
tab . at < float > ( i , 0 ) = matches [ i ] . distance ;
2015-05-04 16:36:24 +08:00
}
2015-05-03 17:42:27 +08:00
sortIdx ( tab , index , SORT_EVERY_COLUMN + SORT_ASCENDING ) ;
2015-05-03 18:04:19 +08:00
vector < DMatch > bestMatches ;
2015-05-03 17:42:27 +08:00
for ( int i = 0 ; i < 30 ; i + + )
2015-05-04 16:36:24 +08:00
{
2015-05-03 17:42:27 +08:00
bestMatches . push_back ( matches [ index . at < int > ( i , 0 ) ] ) ;
2015-05-04 16:36:24 +08:00
}
2015-05-03 17:42:27 +08:00
Mat result ;
drawMatches ( img1 , keyImg1 , img2 , keyImg2 , bestMatches , result ) ;
namedWindow ( * itDesc + " : " + * itMatcher , WINDOW_AUTOSIZE ) ;
imshow ( * itDesc + " : " + * itMatcher , result ) ;
2015-05-07 01:55:16 +08:00
// Saved result could be wrong due to bug 4308
FileStorage fs ( * itDesc + " _ " + * itMatcher + " .yml " , FileStorage : : WRITE ) ;
2015-05-03 17:42:27 +08:00
fs < < " Matches " < < matches ;
vector < DMatch > : : iterator it ;
2015-05-04 16:36:24 +08:00
cout < < " **********Match results********** \n " ;
cout < < " Index \t Index \t distance \n " ;
cout < < " in img1 \t in img2 \n " ;
2015-05-07 01:55:16 +08:00
// Use to compute distance between keyPoint matches and to evaluate match algorithm
double cumSumDist2 = 0 ;
2015-05-04 16:36:24 +08:00
for ( it = bestMatches . begin ( ) ; it ! = bestMatches . end ( ) ; it + + )
{
cout < < it - > queryIdx < < " \t " < < it - > trainIdx < < " \t " < < it - > distance < < " \n " ;
Point2d p = keyImg1 [ it - > queryIdx ] . pt - keyImg2 [ it - > trainIdx ] . pt ;
cumSumDist2 = p . x * p . x + p . y * p . y ;
}
desMethCmp . push_back ( cumSumDist2 ) ;
2015-05-03 17:42:27 +08:00
waitKey ( ) ;
}
}
2015-05-04 16:36:24 +08:00
catch ( Exception & e )
{
2015-05-03 17:42:27 +08:00
cout < < " Feature : " < < * itDesc < < " \n " ;
if ( itMatcher ! = typeAlgoMatch . end ( ) )
2015-05-04 16:36:24 +08:00
{
2015-05-03 17:42:27 +08:00
cout < < " Matcher : " < < * itMatcher < < " \n " ;
2015-05-04 16:36:24 +08:00
}
2015-05-03 17:42:27 +08:00
cout < < e . msg < < endl ;
}
}
2015-05-04 16:36:24 +08:00
int i = 0 ;
cout < < " Cumulative distance between keypoint match for different algorithm and feature detector \n \t " ;
for ( vector < String > : : iterator itMatcher = typeAlgoMatch . begin ( ) ; itMatcher ! = typeAlgoMatch . end ( ) ; itMatcher + + )
{
cout < < * itMatcher < < " \t " ;
}
cout < < " \n " ;
for ( itDesc = typeDesc . begin ( ) ; itDesc ! = typeDesc . end ( ) ; itDesc + + )
{
cout < < * itDesc < < " \t " ;
for ( vector < String > : : iterator itMatcher = typeAlgoMatch . begin ( ) ; itMatcher ! = typeAlgoMatch . end ( ) ; itMatcher + + , i + + )
{
cout < < desMethCmp [ i ] < < " \t " ;
}
cout < < " \n " ;
}
2015-05-03 17:42:27 +08:00
return 0 ;
}