void ImageFeature::flann_demo(Mat& image, Mat& image2) {
//SURF 特征提取
int minHessian = 400;
Ptr<xfeatures2d::SURF> detector = xfeatures2d::SURF::create(minHessian);
vector<KeyPoint> keypoint_obj, keypoint_scene;
Mat descriptor_obj, descriptor_scens;
detector->detectAndCompute(image, Mat(), keypoint_obj, descriptor_obj);
detector->detectAndCompute(image2, Mat(), keypoint_scene, descriptor_scens);
//SURF 特征匹配
FlannBasedMatcher matcher;
vector<DMatch> matches;
matcher.match(descriptor_obj, descriptor_scens, matches);
//查找最大最小距离
double minDist = 1000;
double maxDist = 0;
for (size_t i = 0; i < descriptor_obj.rows; i++) {
double dist = matches[i].distance;
if (dist > maxDist) { maxDist = dist; }
if (dist < minDist) { minDist = dist; }
}
cout << "minDist = " << minDist << endl;
cout << "maxDist = " << maxDist << endl;
// 筛选最佳匹配(小于最小距离的3倍)
vector<DMatch> goodMatchs;
for (size_t i = 0; i < descriptor_obj.rows; i++) {
double dist = matches[i].distance;
if (dist < max(3 * minDist, 0.02)) {
goodMatchs.push_back(matches[i]);
}
}
//绘制特征点
Mat matchImg;
drawMatches(
image, keypoint_obj,
image2, keypoint_scene,
goodMatchs, matchImg,
Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
);
imshow("matchImg", matchImg);
//查看goodMatchs
for (size_t i = 0; i < goodMatchs.size(); i++){
cout << "goodMatchs "<<to_string(i) << "\tKeypoint1, Keypoint2 = " << goodMatchs[i].queryIdx <<", " << goodMatchs[i].trainIdx << endl;
}
//获取goodMatchs坐标,并获取变换矩阵
vector<Point2f> obj;
vector<Point2f> scens;
for (size_t i = 0; i < goodMatchs.size(); i++) {
obj.push_back(keypoint_obj[goodMatchs[i].queryIdx].pt);
scens.push_back(keypoint_scene[goodMatchs[i].trainIdx].pt);
}
Mat H = findHomography(obj, scens, RANSAC);
vector<Point2f> obj_corners(4);
vector<Point2f> scens_corners(4);
obj_corners[0] = Point(0, 0);
obj_corners[1] = Point(image.cols, 0);
obj_corners[2] = Point(image.cols,image.rows);
obj_corners[3] = Point(0, image.rows);
perspectiveTransform(obj_corners, scens_corners, H);
//可视化
line(matchImg, scens_corners[0] + obj_corners[1], scens_corners[1] + obj_corners[1], Scalar(0, 0, 255));
line(matchImg, scens_corners[1] + obj_corners[1], scens_corners[2] + obj_corners[1], Scalar(0, 0, 255));
line(matchImg, scens_corners[2] + obj_corners[1], scens_corners[3] + obj_corners[1], Scalar(0, 0, 255));
line(matchImg, scens_corners[3] + obj_corners[1], scens_corners[0] + obj_corners[1], Scalar(0, 0, 255));
imshow("matchImg2", matchImg);
//绘制到背景图上
Mat image2_BGR;
cvtColor(image2, image2_BGR, COLOR_GRAY2BGR);
line(image2_BGR, scens_corners[0], scens_corners[1], Scalar(0, 0, 255));
line(image2_BGR, scens_corners[1], scens_corners[2], Scalar(0, 0, 255));
line(image2_BGR, scens_corners[2], scens_corners[3], Scalar(0, 0, 255));
line(image2_BGR, scens_corners[3], scens_corners[0], Scalar(0, 0, 255));
imshow("image2_BGR", image2_BGR);
}