//Description: Feature Matching And Detection In OpenCV
//Create Date: 2018-01-01 16:02:39
//Author: channy
Mat readImage(string filename) {
Mat img = imread(filename), imgGray;
if( img.empty()) {
cout << "Couldn'g open image " << filename << ". Usage: detect <image_name>\n";
return Mat();
}
//namedWindow( "image", 1 );
//imshow("image", img);
//waitKey(0);
if (img.channels() == 3) {
cvtColor(img, imgGray, COLOR_BGR2GRAY);
} else {
img.copyTo(imgGray);
}
return imgGray;
}
int main( int argc, char** argv ) {
cv::CommandLineParser parser(argc, argv, "{ @input | ./fruits.jpg | ./fruits.jpg}");
string filename1 = parser.get<string>("@input");
string filename2 = parser.get<string>("@input");
Mat img1 = readImage(filename1);
Mat img2 = readImage(filename2);
vector<KeyPoint> detectKeyPoint1, detectKeyPoint2;
Mat descriptors1, descriptors2;
Ptr<ORB> orb = ORB::create(5000);
orb->detectAndCompute(img1, noArray(), detectKeyPoint1, descriptors1);
orb->detectAndCompute(img2, noArray(), detectKeyPoint2, descriptors2);
if (descriptors1.type() != CV_32F) {
descriptors1.convertTo(descriptors1, CV_32F);
descriptors2.convertTo(descriptors2, CV_32F);
}
FlannBasedMatcher matcher;
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
Mat imgMatch;
drawMatches(img1, detectKeyPoint1, img2, detectKeyPoint2, matches, imgMatch, Scalar::all(-1), Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
imshow("match", imgMatch);
waitKey(0);
return 0;
}
Let’s start at FlannBasedMatcher.match() function. FlannBasedMatcher is a derived class of DescriptorMatcher, then will jump to DescriptorMatcher.match() and enter knnMatch to find the most k nearby matches, seems so easy.
Here we will analyse the implement of Feature Detection in Opencv3.
At the beginning, let’s see how to use opencv to detect features.
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <cstdio>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv ) {
cv::CommandLineParser parser(argc, argv, "{ @input | ./fruits.jpg | }");
string filename = parser.get<string>("@input");
Mat img = imread(filename), imgGray;
if( img.empty() )
{
cout << "Couldn'g open image " << filename << ". Usage: detect <image_name>\n";
return 0;
}
namedWindow( "image", 1 );
imshow("image", img);
if (img.channels() == 3) {
cvtColor(img, imgGray, COLOR_BGR2GRAY);
} else {
img.copyTo(imgGray);
}
vector<KeyPoint> detectKeyPoint;
Mat imgWithKeyPoint;
//Fast
Ptr<FeatureDetector> detector = FastFeatureDetector::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("FAST", 1);
imshow("FAST", imgWithKeyPoint);
//AKAZE
detector = AKAZE::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("akaze", 1);
imshow("akaze", imgWithKeyPoint);
//Brisk
detector = BRISK::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("Brisk", 1);
imshow("Brisk", imgWithKeyPoint);
//GoodFeaturesToTrack
detector = GFTTDetector::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("GoodFeaturesToTrack", 1);
imshow("GoodFeaturesToTrack", imgWithKeyPoint);
//ORB
detector = ORB::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("ORB", 1);
imshow("ORB", imgWithKeyPoint);
//MSER
detector = MSER::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("MSER", 1);
imshow("MSER", imgWithKeyPoint);
//SimpleBlobDetector
detector = SimpleBlobDetector::create();
detector->detect(imgGray, detectKeyPoint);
drawKeypoints(img, detectKeyPoint, imgWithKeyPoint, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
namedWindow("SimpleBlobDetector", 1);
imshow("SimpleBlobDetector", imgWithKeyPoint);
waitKey(0);
return 0;
}
Then we will begin from: FastFeatureDetector::create()
actually, it is: (feature2d/src/fast.cpp)
Ptr<FastFeatureDetector> FastFeatureDetector::create( int threshold, bool nonmaxSuppression, int type ) {
return makePtr<FastFeatureDetector_Impl>(threshold, nonmaxSuppression, type);
}
After create ptr, then we enter detect function of FastFeatureDetector_Impl:
void detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) {
Mat mask = _mask.getMat(), grayImage;
UMat ugrayImage;
_InputArray gray = _image;
if( _image.type() != CV_8U )
{
_OutputArray ogray = _image.isUMat() ? _OutputArray(ugrayImage) : _OutputArray(grayImage);
cvtColor( _image, ogray, COLOR_BGR2GRAY );
gray = ogray;
}
FAST( gray, keypoints, threshold, nonmaxSuppression, type );
KeyPointsFilter::runByPixelsMask( keypoints, mask );
}
First, we need to convert input image to gray image.
Then, follow the kernel function FAST, actually in FAST_t:
template<int patternSize>
void FAST_t(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)