Add Java and Python code for the following features2d tutorials: Harris corner detector, Shi-Tomasi corner detector, Creating your own corner detector, Detecting corners location in subpixels, Feature Detection, Feature Description, Feature Matching with FLANN, Features2D + Homography to find a known object. Use Lowe's ratio test to filter the matches.
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
#include <iostream>
|
||||
#include "opencv2/core.hpp"
|
||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/xfeatures2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::xfeatures2d;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
const char* keys =
|
||||
"{ help h | | Print help message. }"
|
||||
"{ input1 | ../data/box.png | Path to input image 1. }"
|
||||
"{ input2 | ../data/box_in_scene.png | Path to input image 2. }";
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
CommandLineParser parser( argc, argv, keys );
|
||||
Mat img1 = imread( parser.get<String>("input1"), IMREAD_GRAYSCALE );
|
||||
Mat img2 = imread( parser.get<String>("input2"), IMREAD_GRAYSCALE );
|
||||
if ( img1.empty() || img2.empty() )
|
||||
{
|
||||
cout << "Could not open or find the image!\n" << endl;
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
|
||||
int minHessian = 400;
|
||||
Ptr<SURF> detector = SURF::create( minHessian );
|
||||
std::vector<KeyPoint> keypoints1, keypoints2;
|
||||
Mat descriptors1, descriptors2;
|
||||
detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 );
|
||||
detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 );
|
||||
|
||||
//-- Step 2: Matching descriptor vectors with a brute force matcher
|
||||
// Since SURF is a floating-point descriptor NORM_L2 is used
|
||||
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);
|
||||
std::vector< DMatch > matches;
|
||||
matcher->match( descriptors1, descriptors2, matches );
|
||||
|
||||
//-- Draw matches
|
||||
Mat img_matches;
|
||||
drawMatches( img1, keypoints1, img2, keypoints2, matches, img_matches );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow("Matches", img_matches );
|
||||
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
#include <iostream>
|
||||
#include "opencv2/core.hpp"
|
||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/xfeatures2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::xfeatures2d;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
CommandLineParser parser( argc, argv, "{@input | ../data/box.png | input image}" );
|
||||
Mat src = imread( parser.get<String>( "@input" ), IMREAD_GRAYSCALE );
|
||||
if ( src.empty() )
|
||||
{
|
||||
cout << "Could not open or find the image!\n" << endl;
|
||||
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector
|
||||
int minHessian = 400;
|
||||
Ptr<SURF> detector = SURF::create( minHessian );
|
||||
std::vector<KeyPoint> keypoints;
|
||||
detector->detect( src, keypoints );
|
||||
|
||||
//-- Draw keypoints
|
||||
Mat img_keypoints;
|
||||
drawKeypoints( src, keypoints, img_keypoints );
|
||||
|
||||
//-- Show detected (drawn) keypoints
|
||||
imshow("SURF Keypoints", img_keypoints );
|
||||
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
#include <iostream>
|
||||
#include "opencv2/core.hpp"
|
||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/xfeatures2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::xfeatures2d;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
const char* keys =
|
||||
"{ help h | | Print help message. }"
|
||||
"{ input1 | ../data/box.png | Path to input image 1. }"
|
||||
"{ input2 | ../data/box_in_scene.png | Path to input image 2. }";
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
CommandLineParser parser( argc, argv, keys );
|
||||
Mat img1 = imread( parser.get<String>("input1"), IMREAD_GRAYSCALE );
|
||||
Mat img2 = imread( parser.get<String>("input2"), IMREAD_GRAYSCALE );
|
||||
if ( img1.empty() || img2.empty() )
|
||||
{
|
||||
cout << "Could not open or find the image!\n" << endl;
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
|
||||
int minHessian = 400;
|
||||
Ptr<SURF> detector = SURF::create( minHessian );
|
||||
std::vector<KeyPoint> keypoints1, keypoints2;
|
||||
Mat descriptors1, descriptors2;
|
||||
detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 );
|
||||
detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 );
|
||||
|
||||
//-- Step 2: Matching descriptor vectors with a FLANN based matcher
|
||||
// Since SURF is a floating-point descriptor NORM_L2 is used
|
||||
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED);
|
||||
std::vector< std::vector<DMatch> > knn_matches;
|
||||
matcher->knnMatch( descriptors1, descriptors2, knn_matches, 2 );
|
||||
|
||||
//-- Filter matches using the Lowe's ratio test
|
||||
const float ratio_thresh = 0.7f;
|
||||
std::vector<DMatch> good_matches;
|
||||
for (size_t i = 0; i < knn_matches.size(); i++)
|
||||
{
|
||||
if (knn_matches[i].size() > 1 && knn_matches[i][0].distance / knn_matches[i][1].distance <= ratio_thresh)
|
||||
{
|
||||
good_matches.push_back(knn_matches[i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
//-- Draw matches
|
||||
Mat img_matches;
|
||||
drawMatches( img1, keypoints1, img2, keypoints2, good_matches, img_matches, Scalar::all(-1),
|
||||
Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow("Good Matches", img_matches );
|
||||
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#include <iostream>
|
||||
#include "opencv2/core.hpp"
|
||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||
#include "opencv2/calib3d.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
#include "opencv2/xfeatures2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::xfeatures2d;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
const char* keys =
|
||||
"{ help h | | Print help message. }"
|
||||
"{ input1 | ../data/box.png | Path to input image 1. }"
|
||||
"{ input2 | ../data/box_in_scene.png | Path to input image 2. }";
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
CommandLineParser parser( argc, argv, keys );
|
||||
Mat img_object = imread( parser.get<String>("input1"), IMREAD_GRAYSCALE );
|
||||
Mat img_scene = imread( parser.get<String>("input2"), IMREAD_GRAYSCALE );
|
||||
if ( img_object.empty() || img_scene.empty() )
|
||||
{
|
||||
cout << "Could not open or find the image!\n" << endl;
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
|
||||
int minHessian = 400;
|
||||
Ptr<SURF> detector = SURF::create( minHessian );
|
||||
std::vector<KeyPoint> keypoints_object, keypoints_scene;
|
||||
Mat descriptors_object, descriptors_scene;
|
||||
detector->detectAndCompute( img_object, noArray(), keypoints_object, descriptors_object );
|
||||
detector->detectAndCompute( img_scene, noArray(), keypoints_scene, descriptors_scene );
|
||||
|
||||
//-- Step 2: Matching descriptor vectors with a FLANN based matcher
|
||||
// Since SURF is a floating-point descriptor NORM_L2 is used
|
||||
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED);
|
||||
std::vector< std::vector<DMatch> > knn_matches;
|
||||
matcher->knnMatch( descriptors_object, descriptors_scene, knn_matches, 2 );
|
||||
|
||||
//-- Filter matches using the Lowe's ratio test
|
||||
const float ratio_thresh = 0.75f;
|
||||
std::vector<DMatch> good_matches;
|
||||
for (size_t i = 0; i < knn_matches.size(); i++)
|
||||
{
|
||||
if (knn_matches[i].size() > 1 && knn_matches[i][0].distance / knn_matches[i][1].distance <= ratio_thresh)
|
||||
{
|
||||
good_matches.push_back(knn_matches[i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
//-- Draw matches
|
||||
Mat img_matches;
|
||||
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, good_matches, img_matches, Scalar::all(-1),
|
||||
Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
|
||||
|
||||
//-- Localize the object
|
||||
std::vector<Point2f> obj;
|
||||
std::vector<Point2f> scene;
|
||||
|
||||
for( size_t i = 0; i < good_matches.size(); i++ )
|
||||
{
|
||||
//-- Get the keypoints from the good matches
|
||||
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
|
||||
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
|
||||
}
|
||||
|
||||
Mat H = findHomography( obj, scene, RANSAC );
|
||||
|
||||
//-- Get the corners from the image_1 ( the object to be "detected" )
|
||||
std::vector<Point2f> obj_corners(4);
|
||||
obj_corners[0] = Point2f(0, 0);
|
||||
obj_corners[1] = Point2f( (float)img_object.cols, 0 );
|
||||
obj_corners[2] = Point2f( (float)img_object.cols, (float)img_object.rows );
|
||||
obj_corners[3] = Point2f( 0, (float)img_object.rows );
|
||||
std::vector<Point2f> scene_corners(4);
|
||||
|
||||
perspectiveTransform( obj_corners, scene_corners, H);
|
||||
|
||||
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
|
||||
line( img_matches, scene_corners[0] + Point2f((float)img_object.cols, 0),
|
||||
scene_corners[1] + Point2f((float)img_object.cols, 0), Scalar(0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[1] + Point2f((float)img_object.cols, 0),
|
||||
scene_corners[2] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[2] + Point2f((float)img_object.cols, 0),
|
||||
scene_corners[3] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
line( img_matches, scene_corners[3] + Point2f((float)img_object.cols, 0),
|
||||
scene_corners[0] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
|
||||
|
||||
//-- Show detected matches
|
||||
imshow("Good Matches & Object detection", img_matches );
|
||||
|
||||
waitKey();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main()
|
||||
{
|
||||
std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user