My FLANN-matcher doesn't work properly. It finds incorrect points, even though the source object and scene are of good quality.
using namespace cv;
using namespace std;
Mat g_Obj1Image;
Mat g_Obj1Descriptors;
std::vector< KeyPoint > g_Obj1Keypoints;
Mat g_Obj2Image;
Mat g_Obj2Descriptors;
std::vector< KeyPoint > g_Obj2Keypoints;
Mat g_Obj3Image;
Mat g_Obj3Descriptors;
std::vector< KeyPoint > g_Obj3Keypoints;
cv::Ptr<xfeatures2d::SURF> detector;
//cv::Ptr<cv::ORB> detector;
void PrepareObjects(const std::string& obj1, const std::string& obj2, const std::string& obj3)
{
detector = cv::xfeatures2d::SURF::create();
//detector = cv::ORB::create();
detector->setExtended(true);
g_Obj1Image = imread(obj1, IMREAD_GRAYSCALE );
if (g_Obj1Image.data == nullptr)
{
throw std::runtime_error("cannot read image");
}
detector->detectAndCompute( g_Obj1Image, noArray(), g_Obj1Keypoints, g_Obj1Descriptors );
g_Obj2Image = imread(obj2, IMREAD_GRAYSCALE );
if (g_Obj2Image.data == NULL)
{
throw std::runtime_error("cannot read image");
}
detector->detectAndCompute( g_Obj2Image, noArray(), g_Obj2Keypoints, g_Obj2Descriptors );
g_Obj3Image = imread(obj3, IMREAD_GRAYSCALE );
if (g_Obj3Image.data == NULL)
{
throw std::runtime_error("cannot read image");
}
detector->detectAndCompute( g_Obj3Image, noArray(), g_Obj3Keypoints, g_Obj3Descriptors );
}
void flann_test(Mat& frame, Mat& img, Mat& descrs, std::vector< KeyPoint >& keypoints)
{
Mat& obj_image = img;
Mat& obj_descriptors = descrs;
std::vector< KeyPoint >& obj_keypoints = keypoints;
Mat blured;
GaussianBlur(frame, blured, Size(3, 3), 0);
Mat sceneImage;
cvtColor(blured, sceneImage, COLOR_RGB2GRAY);
std::vector< KeyPoint > sceneKeypoints;
Mat sceneDescriptors;
detector->detectAndCompute( sceneImage, noArray(), sceneKeypoints, sceneDescriptors);
//cv::FlannBasedMatcher matcher(cv::makePtr<cv::flann::LshIndexParams>(20, 10, 2));
cv::FlannBasedMatcher matcher;
std::vector<DMatch> matches;
matcher.match( obj_descriptors, sceneDescriptors, matches);
double max_dist = 0;
double min_dist = 100;
for( int i = 0; i < obj_descriptors.rows; i++ ) {
double dist = matches[i].distance;
if( dist < min_dist ) {
min_dist = dist;
}
if( dist > max_dist ) {
max_dist = dist;
}
}
std::vector< DMatch > good_matches;
for( int i = 0; i < obj_descriptors.rows; i++ ) {
if( matches[ i ].distance < 2 * min_dist ) {
good_matches.push_back( matches[ i ] );
}
}
if (good_matches.size() > 3)
{
try {
Mat imgMatches;
drawMatches( obj_image, obj_keypoints, sceneImage, sceneKeypoints,
good_matches, imgMatches, Scalar::all( -1 ), Scalar::all( -1 ),
std::vector< char >(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
imshow( "Good Matches & Object detection", imgMatches);
/*std::vector< Point2f > obj;
std::vector< Point2f > scene;
for( size_t i = 0; i < good_matches.size(); i++ ) {
obj.push_back( obj_keypoints[ good_matches[ i ].queryIdx ].pt );
scene.push_back( sceneKeypoints[ good_matches[ i ].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, RANSAC );
std::vector< Point2f > objCorners( 4 );
objCorners[ 0 ] = Point( 0, 0 );
objCorners[ 1 ] = Point( obj_image.cols, 0 );
objCorners[ 2 ] = Point( obj_image.cols, obj_image.rows );
objCorners[ 3 ] = Point( 0, obj_image.rows );
std::vector< Point2f > sceneCorners( 4 );
perspectiveTransform( objCorners, sceneCorners, H );
line( imgMatches, sceneCorners[ 0 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 1 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
line( imgMatches, sceneCorners[ 1 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 2 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
line( imgMatches, sceneCorners[ 2 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 3 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
line( imgMatches, sceneCorners[ 3 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 0 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
imshow( "Good Matches & Object detection", imgMatches);*/
} catch (const std::exception& ex)
{
std::cout << "EXCEPTION: "<<ex.what() <<std::endl;
}
}
}
int main ( int , char ** )
{
PrepareObjects("/home/zafyrchi/misc/a1.png", "/home/zafyrchi/misc/a2.png", "/home/zafyrchi/misc/a3.png");
cv::namedWindow("Good Matches & Object detection", WINDOW_NORMAL);
cv::Mat frame = cv::imread("/home/zafyrchi/misc/s0.png");
flann_test(frame, g_Obj1Image, g_Obj1Descriptors, g_Obj1Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj2Image, g_Obj2Descriptors, g_Obj2Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj3Image, g_Obj3Descriptors, g_Obj3Keypoints); cv::waitKey(3000);
frame = cv::imread("/home/zafyrchi/misc/s1.png");
flann_test(frame, g_Obj1Image, g_Obj1Descriptors, g_Obj1Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj2Image, g_Obj2Descriptors, g_Obj2Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj3Image, g_Obj3Descriptors, g_Obj3Keypoints); cv::waitKey(3000);
frame = cv::imread("/home/zafyrchi/misc/s2.png");
flann_test(frame, g_Obj1Image, g_Obj1Descriptors, g_Obj1Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj2Image, g_Obj2Descriptors, g_Obj2Keypoints); cv::waitKey(3000);
flann_test(frame, g_Obj3Image, g_Obj3Descriptors, g_Obj3Keypoints); cv::waitKey(3000);
return 0;
}
Source objects:
Scenes: