接着上篇FLANN特征匹配,从上篇可以知道,如果特征匹配时全部是用线进行匹配,匹配效果并不能达到一目了然的效果
那么,可不可以把匹配到的结果用矩形或圆表示出来呢 当然可以,这就是平面对象识别
关于基于透视变换的平面对象识别
主要用到两个新的API
cv::findHomography() – 发现两个平面的透视变换,生成透视变换矩阵
cv::perspectiveTransform() – 进行透视变换
关于透视变换
透视变换(Perspective Transformation)可以对图片进行校正 也可以通过透视变换进行图像的平面识别
透视变换(Perspective Transformation)是指利用透视中心、像点、目标点三点共线的条件,
按透视旋转定律使承影面(投影面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,
仍能保持承影面上投影几何图形不变的变换
用单应矩阵透视变换进行图像矫正,最少需要四个对应点对
关于基于透视变换的图像校正
透视变换对畸变图像的校正需要取得畸变图像的一组4个点的坐标,和目标图像的一组4个点的坐标,通过两组坐标点可以计算出透视变换的变换矩阵,之后对整个原始图像执行变换矩阵的变换,就可以实现图像校正
图像校正API
cv::warpPerspective对翘曲图像进行校正显示
代码演示
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
int Osize = 3;
Mat SenceIMG, ObjIMG, dst;
void FLANNdetector(int, void*);
void WarpPerspective(int, void*);
int main()
{
ObjIMG = imread("D:/实验台/机器视觉/测试图片/自由女神小.jpg", IMREAD_GRAYSCALE);//训练图像
SenceIMG = imread("D:/实验台/机器视觉/测试图片/自由女神像.jpg", IMREAD_GRAYSCALE);//查询图像
if (SenceIMG.empty() || ObjIMG.empty())//如果SenceIMG这个数据库属性为空
{
cout << "无法打开" << endl;
return -1;
}
imshow("训练图像", SenceIMG);
imshow("查询图像", ObjIMG);
namedWindow("透视变换画出目标轮廓的效果", CV_WINDOW_AUTOSIZE);
createTrackbar("最大允许重投影错误阈值", "透视变换画出目标轮廓的效果", &Osize, 150, FLANNdetector);
FLANNdetector(0, 0);
WarpPerspective(0, 0);
waitKey(0);
return 0;
}
FLANN特征检测
void FLANNdetector(int, void*)
{
//copy自FLANN特征检测项目的代码
int minHessian = 400;//特征检测器阈值
Ptr<SURF> detector = SURF::create(minHessian);//构建SURF类的特征点检测器
vector<KeyPoint>keypointOBJ; // 设置用于存放第一张图特征点信息的 KeyPoint类的集合向量 keypoints
vector<KeyPoint>keypointSCENE;//同上 待匹配的第二张图的特征点信息
Mat descriptorOBJ, descriptorSCENE; //建立两个描述符集矩阵分别存放图一的查询描述集和图二的训练描述集合
//进行对两张需要进行匹配的图像的特征提取和描述符信息的计算
detector->detectAndCompute(ObjIMG, Mat(), keypointOBJ, descriptorOBJ);
detector->detectAndCompute(SenceIMG, Mat(), keypointSCENE, descriptorSCENE);
//todocv :: Feature2D :: detectAndCompute检测特征点并计算其描述子的函数(使用detector这个检测器)
基于Flann类型的描述符匹配器
FlannBasedMatcher matcher;
//todo建立查询训练集中的描述符得出的 匹配项描述符 所需要的动态向量DMatch类数组
vector<DMatch>matches;//未进行筛选前的匹配描述符
matcher.match(descriptorOBJ, descriptorSCENE, matches);
//todovoid cv::DescriptorMatcher::match使用建立好的Flann匹配器matcher进行匹配
//匹配相关度最高的特征点过滤不相干的特征点
double minDist = 1000;
double maxDist = 0;
//通过遍历两个匹配的特征向量之间的欧氏距离(距离越近匹配度越高)进行精确特征点的筛选
for (int i = 0; i < descriptorOBJ.rows