opencv AKAZE 特征点提取
本章内容
1. AKAZE 特征点提取
2. 计算特征描述子
3. FLANN特征匹配
4. 绘制匹配结果
1. AKAZE 特征点提取
输出结果:
2. 单应性变换,平面对象
输出结果
源码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>int main(int argc, char* argv[]){
/*本章内容
1. AKAZE 特征点提取
2. 计算特征描述子
3. FLANN特征匹配
4. 绘制匹配结果
*/cv::Mat src = cv::imread("/home/wang/dev/Image/book.png",cv::IMREAD_REDUCED_COLOR_2);
cv::Mat src1 = cv::imread("/home/wang/dev/Image/books.jpg",cv::IMREAD_REDUCED_COLOR_8);if(src.empty() || src1.empty()){
std::cout << "图像文件读入失败\n" <<std::endl;
return -1;
}
cv::imshow("src",src);
cv::imshow("src1",src1);
/*1. AKAZE 特征点提取
* api接口: CV_WRAP static Ptr<AKAZE> create(AKAZE::DescriptorType descriptor_type = AKAZE::DESCRIPTOR_MLDB,
int descriptor_size = 0, int descriptor_channels = 3,
float threshold = 0.001f, int nOctaves = 4,
int nOctaveLayers = 4, KAZE::DiffusivityType diffusivity = KAZE::DIFF_PM_G2);
@param descriptor_type Type of the extracted descriptor: DESCRIPTOR_KAZE,
DESCRIPTOR_KAZE_UPRIGHT, DESCRIPTOR_MLDB or DESCRIPTOR_MLDB_UPRIGHT.
@param descriptor_size Size of the descriptor in bits. 0 -\> Full size
@param descriptor_channels Number of channels in the descriptor (1, 2, 3)
@param threshold Detector response threshold to accept point
@param nOctaves Maximum octave evolution of the image
@param nOctaveLayers Default number of sublevels per scale level
@param diffusivity Diffusivity type. DIFF_PM_G1, DIFF_PM_G2, DIFF_WEICKERT or
DIFF_CHARBONNIER
*/
cv::Ptr<cv::AKAZE> akaze = cv::AKAZE::create();
std::vector<cv::KeyPoint> kps1;
akaze->detect(src,kps1);
cv::Mat dst;
cv::drawKeypoints(src,kps1,dst);
cv::imshow("akaze keypoint",dst);// 2.计算特征描述子
std::vector<cv::KeyPoint> kp1;
std::vector<cv::KeyPoint> kp2;
cv::Mat des1;
cv::Mat des2;
akaze->detectAndCompute(src,cv::Mat(),kp1,des1);
akaze->detectAndCompute(src1,cv::Mat(),kp2,des2);// 3.FLANN特征匹配
// LshIndexParams(int table_number, int key_size, int multi_probe_level);
cv::flann::LshIndexParams Lsh(20, 10, 2);
cv::FlannBasedMatcher matcher(&Lsh);
std::vector<cv::DMatch> Dmatch;
matcher.match(des1,des2,Dmatch);
cv::Mat dstMatch;
// 搜索最大最小距离
double minDist = 1000;
double maxDist = 0;
for(int i=0; i < Dmatch.size();i++){
if(Dmatch[i].distance > maxDist) maxDist = Dmatch[i].distance ;
if(Dmatch[i].distance < minDist) minDist = Dmatch[i].distance ;
}
// 提取优质匹配点
std::vector<cv::DMatch> goodMatchers;
for(int i=0; i < Dmatch.size();i++){
if(Dmatch[i].distance < cv::max(maxDist*0.8, 0.02)) goodMatchers.push_back(Dmatch[i]);
}
// 绘制匹配结果
// cv::Mat dst;
// 计算单应性矩阵
std::vector<cv::Point2f> pt1s;
std::vector<cv::Point2f> pt2s;
for(int i=0; i < goodMatchers.size(); i++){
pt1s.push_back(kp1[goodMatchers[i].queryIdx].pt);
pt2s.push_back(kp2[goodMatchers[i].trainIdx].pt);
}
cv::Mat Hom = cv::findHomography(pt1s,pt2s,cv::RANSAC);
std::cout << "单应性矩阵:\n" << Hom << std::endl;// 透视变换
std::vector<cv::Point2f> p1;
p1.push_back(cv::Point2f(0,0));
p1.push_back(cv::Point2f(0,src.cols));
p1.push_back(cv::Point2f(src.rows,src.cols));
p1.push_back(cv::Point2f(src.rows,0));
std::vector<cv::Point2f> p2;
cv::perspectiveTransform(p1,p2,Hom);// 绘制结果
for(int i =0; i <4 ;i++) cv::line(src1,p2[i],p2[(i+1)%4],cv::Scalar(0,255,0),4);
cv::drawMatches(src,kp1,src1,kp2,goodMatchers,dst);
cv::imshow("FLNN匹配结果",dst);
cv::waitKey(0);
return 1;
}