opencv学习笔记三十六:AKAZE特征点检测与匹配

KAZE是日语音译过来的 , KAZE与SIFT、SURF最大的区别在于构造尺度空间,KAZE是利用非线性方式构造,得到的关键点也就更准确(尺度不变性 );

Hessian矩阵特征点检测 ,方向指定,基于一阶微分图像(旋转不变性 ) ;

描述子生成 ,归一化处理(光照不变性 );

AKAZE局特征点检测与匹配 A表示Accelerated(加速的) 与SIFT、 SUFR比较: 更加稳定 非线性尺度空间 AKAZE速度更加快。

#include<opencv2\opencv.hpp>
#include<opencv2\xfeatures2d.hpp>
using namespace cv;
using namespace std;
using namespace xfeatures2d;
Mat src1,src2, dst;
int main(int arc, char** argv) { 
	src1 = imread("1.png",IMREAD_GRAYSCALE);
	src2 = imread("2.png", IMREAD_GRAYSCALE);
	namedWindow("input1", CV_WINDOW_AUTOSIZE);
	imshow("input1", src1);
	/*double t1 = getTickCount();
	  kaze->detect(src1, keypoints1, Mat());
	  double t2 = getTickCount();
	  double time = (t2 - t1) / getTickFrequency();
	  KAZE检测需要2点多秒,如果使用AKAZE即accleration加速的KAZE只需要0点几秒*/
	//AKAZE detect 
	Ptr<AKAZE>akaze = AKAZE::create();
	vector<KeyPoint> keypoints1, keypoints2;
	Mat descriptors1, descriptors2;
	akaze->detectAndCompute(src1, Mat(), keypoints1, descriptors1);
	akaze->detectAndCompute(src2, Mat(), keypoints2, descriptors2);
	//BruteForce match
	BFMatcher matcher;
	vector<DMatch>matches;
	matcher.match(descriptors1, descriptors2, matches);
	Mat akaze_match_img;
	drawMatches(src1, keypoints1, src2, keypoints2, matches, akaze_match_img);
	imshow("output1", akaze_match_img);
	//good matches
	double minDist = 1000;
	double maxDist = 0;
	for (int i = 0; i < descriptors1.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < minDist) 
		{ 
			minDist = dist; 
		}
	}
	printf("%f\n", minDist);
	vector<DMatch>goodMatches;
	for (int i = 0; i < descriptors1.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < max(1.5 * minDist, 0.02))
		{
			goodMatches.push_back(matches[i]);
		}		
	}
	//draw good_match_img
	Mat good_match_img;
	drawMatches(src1, keypoints1, src2, keypoints2, goodMatches, good_match_img, Scalar::all(-1),Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	imshow("output2", good_match_img);
	//perspective transform
	vector<Point2f>src1GoodPoints;
	vector<Point2f>src2GoodPoints;
	for (int i = 0; i < goodMatches.size(); i++)
	{
		src1GoodPoints.push_back(keypoints1[goodMatches[i].queryIdx].pt);
		src2GoodPoints.push_back(keypoints2[goodMatches[i].trainIdx].pt);
	}
	Mat P = findHomography(src1GoodPoints, src2GoodPoints,RANSAC);//有不良匹配点时用RANSAC
	vector<Point2f>src1corner(4);
	vector<Point2f>src2corner(4);
	src1corner[0] = Point(0, 0);
	src1corner[1] = Point(src1.cols, 0);
	src1corner[2] = Point(src1.cols, src1.rows);
	src1corner[3] = Point(0,src1.rows);
	perspectiveTransform(src1corner, src2corner, P);
	//在匹配图上画
	line(good_match_img, Point(src2corner[0].x + src1.cols, src2corner[0].y), Point(src2corner[1].x + src1.cols, src2corner[1].y), Scalar(0, 0,255),2);
	line(good_match_img, Point(src2corner[1].x + src1.cols, src2corner[1].y), Point(src2corner[2].x + src1.cols, src2corner[2].y), Scalar(0, 0, 255),2);
	line(good_match_img, Point(src2corner[2].x + src1.cols, src2corner[2].y), Point(src2corner[3].x + src1.cols, src2corner[3].y), Scalar(0, 0, 255), 2);
	line(good_match_img, Point(src2corner[3].x + src1.cols, src2corner[3].y), Point(src2corner[0].x + src1.cols, src2corner[0].y), Scalar(0, 0, 255),2);
	/*
	//在原图上画
	line(src2, src2corner[0], src2corner[1], Scalar(0, 0, 255),2);
	line(src2, src2corner[1], src2corner[2], Scalar(0, 0, 255), 2);
	line(src2, src2corner[2], src2corner[3], Scalar(0, 0, 255), 2);
	line(src2, src2corner[3], src2corner[0], Scalar(0, 0, 255), 2);
	*/
	imshow("result", good_match_img);
	waitKey(0);
	return 0;
}

暴力匹配结果如下:

 优良匹配结果图如下:

 

 透视变换检测对象如下:

​​

猜你喜欢

转载自blog.csdn.net/qq_24946843/article/details/82701657