文章目录

  • 一、FLANN简介
    • 演示SURF--Flann
  • 二、单应性矩阵

一、FLANN简介

FLANN库全称是Fast Library for Approximate Nearest Neighbors(快速最近邻逼进搜索库),是一个在高维空间快速搜索近邻的库,它是目前最完整的(近似)最近邻开源库。不但实现了一系列查找算法,还包含了一种自动选取最快算法的机制。

主要优势:实现了包含kd-tree等在内的搜索算法集合,并且可以根据数据集本身特点,自动选取最适合的算法来完成k近邻搜索任务(更加确切的说是高维特征向量的匹配任务),提供了c++、c、python、matlab的接口。

FLANN 算法 官网:https://www.cs.ubc.ca/paper/flann
FLANN github地址:https://github.com/flann-lib/flann

关于算法详情查看:https://blog.csdn.net/Bluenapa/article/details/88371512
关于特征存储查看:OpenCV—python 角点特征检测之三(FLANN匹配)
关于构造函数查看:https://www.jianshu.com/p/d70d9c8b2bec

主要介绍一下indexParams的参数

Ptr<flann::IndexParams> indexParams; 索引参数
Ptr<flann::SearchParams> searchParams; 搜索参数
Ptr<flann::Index> flannIndex; 创建索引

头文件 image_feature_all.h:声明类与公共函数

#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/xfeatures2d.hpp>  //新增引入库using namespace cv;
using namespace std;class ImageFeature {public:void flann_demo(Mat& image, Mat& image2);};

主函数main.cpp调用该类的公共成员函数

#include "image_feature_all.h"int main(int argc, char** argv) {const char* img_path = "D:\\Desktop\\match_dst.jpg";const char* img_path2 = "D:\\Desktop\\match_raw.jpg";Mat image = imread(img_path, IMREAD_GRAYSCALE);Mat image2 = imread(img_path2, IMREAD_GRAYSCALE);if (image.empty() || image2.empty()) {cout << "图像数据为空,读取文件失败!" << endl;}ImageFeature imgfeature;imgfeature.flann_demo(image, image2);waitKey(0);destroyAllWindows();return 0;
}

演示SURF–Flann

源文件 feature_extract.cpp:实现类与公共函数

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);//查看goodMatchsfor (size_t i = 0; i < goodMatchs.size(); i++){cout << "goodMatchs "<<to_string(i) << "\tKeypoint1, Keypoint2 = " << goodMatchs[i].queryIdx <<", " << goodMatchs[i].trainIdx << endl;}
}

二、单应性矩阵

从场景图像上得到特征匹配图像的四点坐标:详情请查看

函数介绍:findHomography有三个重载函数,这里只说明一个

Mat findHomography(

InputArray srcPoints,        特征点集合,一般是来自目标图像
InputArray dstPoints,        特征点集合,一般是来自场景图像
int method = 0,           配准方法,支持有四种方法(如下)
double ransacReprojThreshold = 3,      
OutputArray mask=noArray(),     掩码
const int maxIters = 2000,      最大迭代次数,当使用RANSAC方法
const double confidence = 0.995   置信参数
);

method
0 – 使用所有的点,比如最小二乘
RANSAC – 基于随机样本一致性
LMEDS – 最小中值
RHO –基于渐近样本一致性

void perspectiveTransform(
InputArray src,      输入四个顶点
OutputArray dst,      输出四个顶点(变换后)
InputArray m      仿射变换矩阵
)
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);//查看goodMatchsfor (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);
}

OpenCV + CPP 系列(卌一)图像特征匹配( FLANN 匹配)相关推荐

  1. OpenCV入门系列 —— cv::dilate 图像膨胀

    OpenCV入门系列 -- cv::dilate 图像膨胀 前言 程序说明 输出结果 代码示例 前言 随着工业自动化.智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别 ...

  2. OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)

    文章目录 一.KAZE简介 二.代码演示 特征检测效果对比 演示匹配 一.KAZE简介 ECCV2012中出现了一种比SIFT更稳定的特征检测算法KAZE ([1]).KAZE的取名是为了纪念尺度空间 ...

  3. OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)

    文章目录 一.常用图像特征描述 二.Harris角点检测 演示Harris角点检测 三.Shi-Tomasi角点检测 四.自定义角点检测器 一.常用图像特征描述 SIFT.SURF.HOG.Haar. ...

  4. OpenCV + CPP 系列(卅五)图像特征提取(SURF特征检测、SIFT特征检测)

    文章目录 一.SIFT特征检测 二.SURF特征检测 演示SURF.SIFT特征检测 OpenCV-python 角点特征检测之二(SIFT.SURF.ORB) 一.SIFT特征检测 SIFT(Sca ...

  5. 结合openCV学习DIP之传统图像特征与匹配

    前言 关于图像的预处理部分参考  结合opencv学习DIP​​​​​​​ 概述 该笔记主要是基于DIP理论➕openCV实现,学习该笔记首先要确保通读DIP理论,并由自己的话描述相关知识,并且掌握o ...

  6. OpenCV入门系列2:图像叠加、填充和腐蚀

    文章目录 前言 一.图像的叠加 1.1 叠加原理 1.2 叠加问题 1.3 问题解决 1.4 结果展示 二.图像的填充 2.1 填充方法介绍 2.2 复制法 2.3 轴对称法 2.4 中心对称法 2. ...

  7. OpenCV + CPP 系列(卅九)图像特征提取(Haar特征)

    文章目录 Haar特征介绍(Haar Like Features) Haar特征介绍(Haar Like Features) Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征.它分为 ...

  8. OpenCV + CPP 系列(卅四)图像特征提取(亚像素级别角点检测)

    文章目录 亚像素级别角点检测 演示像素坐标检测 亚像素级别角点检测 亚像素:在生成数字图像处理时(拍照等)我们是将物理世界中连续的图像进行了离散化处理.现实世界中颜色为连续的且有无数种类,成像到像素面 ...

  9. OpenCV + CPP 系列(十九)直方图比较 与 直方图反向投影,投影分割

    文章目录 一.直方图比较 计算公式 效果演示 二.直方图反向投影 三.投影分割 一.直方图比较 对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离 ...

最新文章

  1. 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记20 Multiple MVCs 多MVC模式、NavigationController导航控制器...
  2. 为什么要关闭 MySQL Query Cache?
  3. luogu P2241 统计方形
  4. centos内核编译与其签名机制
  5. 我的世界服务器的文件名叫什么,我的世界 外国服务器叫什么名字 | 手游网游页游攻略大全...
  6. mysql存储过程实va_mysql-存储过程(二)-逻辑判断语句
  7. Bootstrap3 行内表单
  8. Vue下载文件不成功及下载文件名称问题
  9. 英特尔hd630驱动_英特尔Iris HD Graphics显卡驱动64位_ intel驱动-PChome下载中心
  10. 吴伯凡-认知方法论-为什么说“盲维”是认知升级的重要概念
  11. 2017中国之旅系列之十一:山西绵山之旅(上)
  12. 钉钉扫码登录二维码错乱
  13. Windows10莫名其妙多了个CD驱动器,删除方法记录
  14. python scratch 图形化_走进Scratch图形化编程
  15. 今天分享一个用Python来爬取小说的小脚本!(附源码)
  16. 医学研究人员为什么要学习R语言?哪本书最适合学习?
  17. 报名成功冲向高级软件工程师之路开始了
  18. 【科普】cmd是什么?
  19. python+appium例子
  20. day03-数据库概念mongodb使用数据库CLUD操作

热门文章

  1. 关于华为DevEco studio2.0的安装和运行第一个hello world的文章
  2. 关于手机刷机备份资料的问题
  3. 【JZOJ5353】村通网
  4. 线控转向系统的carsim与simulink联合仿真
  5. JAVA Spring 事务管理事务不回滚问题
  6. HIS接口--LIS 与 HIS 跳转URL
  7. vue引入地图,实现搜索添加地图位置点,点击地图获取位置信息
  8. 为什么计算机的网络id,网络ID、主机ID和子网掩码
  9. TF Live 直播回放丨Frank Wu:当OpenStack遇到Tungsten Fabric
  10. pwd和$PWD的联系与区别