OpenCV单应性矩阵发现参数估算方法详解

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自:opencv学堂

单应性矩阵计算函数与应用

OpenCV在通过特征描述子完成描述子匹配之后,会得到一些关键点对,我们会把这些关键点对分别添加到两个vector对象中,作为输入参数,调用单应性矩阵发现函数来发现一个变换矩阵H,函数 findHomography 就完成了这样的功能,常见的调用代码如下:

 1//-- Localize the object
 2std::vector<Point2f> obj_pts;
 3std::vector<Point2f> scene_pts;
 4for (size_t i = 0; i < goodMatches.size(); i++)
 5{
 6         //-- Get the keypoints from the good matches
 7         obj_pts.push_back(keypoints_obj[goodMatches[i].queryIdx].pt);
 8         scene_pts.push_back(keypoints_sence[goodMatches[i].trainIdx].pt);
 9}
10Mat H = findHomography(obj_pts, scene_pts, RHO);

有了变换矩阵H之后,我们就可以根据输入图像四点坐标,从场景图像上得到特征匹配图像的四点坐标,代码实现如下:

1//-- Get the corners from the image_1 ( the object to be "detected" )
2std::vector<Point2f> obj_corners(4);
3obj_corners[0] = Point(0, 0); obj_corners[1] = Point(box.cols, 0);
4obj_corners[2] = Point(box.cols, box.rows); obj_corners[3] = Point(0, box.rows);
5std::vector<Point2f> scene_corners(4);
6perspectiveTransform(obj_corners, scene_corners, H);

其中scene_corners为对象在场景图像中的四点坐标,获得坐标以后就可以绘制对应的矩形,从而在场景图像中绘制对象的外接矩形区域。运行结果如下:

上述步骤中最重要的就是单应性矩阵H的计算,这里我们首先来看一下该函数与其各个参数解释:

1Mat cv::findHomography       (       
2     InputArray      srcPoints,
3     InputArray      dstPoints,
4     int   method = 0,
5     double    ransacReprojThreshold = 3,
6     OutputArray   mask = noArray(),
7     const int         maxIters = 2000,
8     const double  confidence = 0.995
9)

参数解释如下:
srcPoints:特征点集合,一般是来自目标图像
dstPoints:特征点集合,一般是来自场景图像
method:表示使用哪种配准方法,支持有四种方法(后续详细说)

  • 0 – 使用所有的点,比如最小二乘

  • RANSAC – 基于随机样本一致性

  • LMEDS – 最小中值

  • RHO –基于渐近样本一致性

ransacReprojThreshold:该参数只有在method参数为RANSAC与RHO的时启用,默认为3
mask:遮罩,当method方法为RANSAC 或 LMEDS可用
maxIters:最大迭代次数,当使用RANSAC方法
confidence:置信参数,默认为0.995

单应性矩阵H发现方法

首先简单的解释一下H的作用,假设在特征匹配或者对齐,视频移动估算中有两张图像image1与image2,image1上有特征点(x1,y1)匹配image2上的特征点(x2,y2),现在我们需要在两者之间建立一种视图变换关系(透视变换),图示如下(图二):

其中H是一个3x3的矩阵

这样为了求出H中的参数,需要两个点对集合,就是findHomography函数中前两个输入参数,理想情况下,通过特征提取得到特征点会再下一帧或者场景图像中保持不变,但是实际情况下,收到各种因素的影响,会额外产生很多特征点或者干扰点,如果正确的剔除这些干扰点,得到正确匹配的点,利用正确匹配点计算出H才是比较稳定的方式。

01

最小二乘拟合

很明显,图二所示的是一个过约束问题,如果没有干扰点的话,就可以通过最小二乘进行直接拟合,求的参数,其中错误计算如下:

基于过约束方程计算得到错误,反向传播不断更新参数,直到两次错误差值满足要求阈值为止。

02

RANSAC

最小二乘方法在描述子匹配输出的点对质量很好,理想情况下是图像没有噪声污染与像素迁移与光线恒定,但是实际情况下图像特别容易受到光线、噪声导致像素迁移,从而产生额外的多余描述子匹配,这些点对可以分为outlier跟inlier两类,基于RANSAC(Random Sample Consensus)可以很好的过滤掉outlier点对,使用合法的点对得到最终的变换矩阵H。RANSAC算法基本思想是,它会从给定的数据中随机选取一部分进行模型参数计算,然后使用全部点对进行计算结果评价,不断迭代,直到选取的数据计算出来的错误是最小,比如低于0.5%即可,完整的算法流程步骤如下:

  1. 选择求解模型要求的最少要求的随机点对

  2. 根据选择随机点对求解/拟合模型得到参数

  3. 根据模型参数,对所有点对做评估,分为outlier跟inlier

  4. 如果所有inlier的数目超过预定义的阈值,则使用所有inlier重新评估模型参数,停止迭代

  5. 如果不符合条件则继续1~4循环。

通常迭代次数N会选择一个比较高的值,OpenCV中默认迭代次数为200,确保有一个随机选择点对不会有outlier数据,

03

PROSAC(RHO)

注意有时候RANSAC方法不会收敛,导致图像对齐或者配准失败,原因在于RANSAC是一种全随机的数据选取方式,完全没有考虑到数据质量不同。对RANSAC算法的改进算法就是PROSAC(Progressive Sampling Consensus)即渐近样本一致性,该方法采用半随机方法,对所有点对进行质量评价计算Q值,然后根据Q值降序排列,每次只在高质量点对中经验模型假设与验证,这样就大大降低了计算量,在RANSAC无法收敛的情况下,PROSAC依然可以取得良好的结果。OpenCV中的RHO方法就是基于PROSAC估算。

04

LMEDS

最小中值方法拟合,该方法可以看成是最小二乘法的改进,原因在于计算机视觉的输入数据是图像,一般都是各自噪声,这种情况下最小二乘往往无法正确拟合数据,所以采用最小中值方法可以更好实现拟合,排除outlier数据。但是它是对高斯噪声敏感算法。它的最主要步骤描述如下:

  1. 随机选取很多个子集从整个数据集中

  2. 根据各个子集数据计算参数模型

  3. 使用计算出来的参数对整个数据集计算中值平方残差

  4. 最终最小残差所对应的参数即为拟合参数。

05

对比测试

最后看一下OpenCV中使用单应性矩阵发现对相同的特征点对,分别使用RANSAC、PROSAC、LMEDS进行参数矩阵H的求解结果对比,显示如下:

总数446个匹配点对,三种评估方式生成的H矩阵(3x3)很明显值都不尽相同。

一般情况下在,推荐大家使用RANSAC或者RHO。默认的0表示最小二乘方法,对图像匹配在实际应用中一般都是翻车!LMEDS方法只有在inlier超过50%以上情况下才会拟合生成比较好的H参数,而RANSAC或者RHO不管outlier跟inlier比率是多少都会可以适用,可以大家也都注意到h33总是等于1,因为h33在这里作用是保持标准化尺度。在OpenCV中如果无法正确估算参数H,会返回空Mat对象。

单应性矩阵应用

图像透视变换与对象匹配

图像拼接

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

单应性矩阵(Homography Matrix)是计算机视觉中常用的一种变换矩阵,可以将一个平面上的点映射到另一个平面上的对应点。在OpenCV中,可以使用findHomography函数来估计两个平面之间的单应性矩阵。下面是一个简单的示例代码: ``` #include <opencv2/opencv.hpp> using namespace cv; int main() { // 读取图像 Mat src1 = imread("image1.jpg"); Mat src2 = imread("image2.jpg"); // 定义特征点向量和描述子向量 std::vector<KeyPoint> keypoints1, keypoints2; Mat descriptors1, descriptors2; // 提取特征点和描述子 Ptr<ORB> orb = ORB::create(); orb->detectAndCompute(src1, noArray(), keypoints1, descriptors1); orb->detectAndCompute(src2, noArray(), keypoints2, descriptors2); // 匹配特征点 BFMatcher matcher(NORM_HAMMING); std::vector<DMatch> matches; matcher.match(descriptors1, descriptors2, matches); // 筛选出最佳匹配 double min_dist = 1000; for (int i = 0; i < descriptors1.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) min_dist = dist; } std::vector<DMatch> good_matches; for (int i = 0; i < descriptors1.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } // 提取匹配点对 std::vector<Point2f> points1, points2; for (int i = 0; i < good_matches.size(); i++) { points1.push_back(keypoints1[good_matches[i].queryIdx].pt); points2.push_back(keypoints2[good_matches[i].trainIdx].pt); } // 计算单应性矩阵 Mat H = findHomography(points1, points2, RANSAC); return 0; } ``` 在这个示例代码中,我们首先使用ORB算法提取了两幅图像的特征点和描述子。然后使用BFMatcher算法匹配了两幅图像的特征点,并筛选出最佳匹配。接下来,我们使用findHomography函数估计了两个平面之间的单应性矩阵。最后,我们可以使用这个单应性矩阵来进行图像配准或者图像拼接等操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值