在OpenCV里使用特征匹配和单映射变换的代码详解


Posted in Python onOctober 23, 2019

前面已经学习特征查找和对应匹配,接着下来在特征匹配之后,再使用findHomography函数来找出对应图像的投影矩阵。首先使用一个查询图片,然后在另外一张图片里找到目标对象,其实就是想在图片里查找所需要目标的一部分区域。为了实现这样的功能,需要使用calib3d库里的一个函数cv.findHomography(),把从两张图片里找到的特征点当作参数,传送给这个函数,然后这个函数返回一个投影变换矩阵,我们就可以使用 cv.perspectiveTransform()函数来对查找的目标进行投影,这样就可以在复杂图片里标记出相应的目标位置。

我们已经看到,在匹配时可能会有一些错误,这可能会影响结果。为了解决这个问题,需要使用RANSAC 或 LEAST_MEDIAN算法。所以提供正确估计的良好匹配称为内聚,其余的称为外联。cv.findHomography()函数返回一个值表示内聚还是外联的点。

在例子里,先使用ORB来寻找两个图片的特征点,接着根据设置条件为10个匹配特征,如果满足就会计算投影变换矩阵,一旦获得3x3的矩阵,就可以把寻找的目标对象在图片里标记出来。最后在复杂的图片里用白色线条标记出来。

在OpenCV里使用特征匹配和单映射变换的代码详解

参数详解:

srcPoints 源平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector<Point2f>类型

dstPoints 目标平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector<Point2f>类型

method 计算单应矩阵所使用的方法。不同的方法对应不同的参数,具体如下:

0 - 利用所有点的常规方法

RANSAC - RANSAC-基于RANSAC的鲁棒算法

LMEDS - 最小中值鲁棒算法

RHO - PROSAC-基于PROSAC的鲁棒算法

ransacReprojThreshold

将点对视为内点的最大允许重投影错误阈值(仅用于RANSAC和RHO方法)。如果

则点被认为是个外点(即错误匹配点对)。若srcPoints和dstPoints是以像素为单位的,则该参数通常设置在1到10的范围内。

mask

可选输出掩码矩阵,通常由鲁棒算法(RANSAC或LMEDS)设置。 请注意,输入掩码矩阵是不需要设置的。

maxIters RANSAC算法的最大迭代次数,默认值为2000。

confidence 可信度值,取值范围为0到1.

该函数能够找到并返回源平面和目标平面之间的转换矩阵H,以便于反向投影错误率达到最小。

在OpenCV里使用特征匹配和单映射变换的代码详解

演示使用的例子如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
 
MIN_MATCH_COUNT = 10
 
#读取文件
img1 = cv2.imread('rmb3.png')
img2 = cv2.imread('rmb4.png')
 
#初始化ORB检测器
orb = cv2.ORB_create()
 
#用ORB查找关键点
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
 
# FLANN参数
FLANN_INDEX_LSH = 6
index_params = dict(algorithm = FLANN_INDEX_LSH,
          table_number = 6, 
          key_size = 12,   
          multi_probe_level = 1)
search_params = dict(checks=50)  #或者使用一个空的字典
flann = cv2.FlannBasedMatcher(index_params,search_params)
 
matches = flann.knnMatch(des1,des2,k=2)
 
# 比率
good = []
for m,n in matches:
  if m.distance < 0.7*n.distance:
    good.append(m)
if len(good)>MIN_MATCH_COUNT:
  src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
  dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
  #找到投影变换矩阵
  M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
  matchesMask = mask.ravel().tolist()
  #进行投影变换
  h,w,d = img1.shape
  pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
  dst = cv2.perspectiveTransform(pts,M)
  #画变换后的外形
  img2 = cv2.polylines(img2,[np.int32(dst)],True,(255,255,255),3, cv2.LINE_AA)
 
else:
  print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
  matchesMask = Non
 
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
          singlePointColor = None,
          matchesMask = matchesMask, # draw only inliers
          flags = 2)
 
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
 
#显示图片
cv2.imshow('img3',img3)
      
cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

在OpenCV里使用特征匹配和单映射变换的代码详解

总结

以上所述是小编给大家介绍的在OpenCV里使用特征匹配和单映射变换的代码详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python中查看变量内存地址的方法
May 05 Python
详解Python中的元组与逻辑运算符
Oct 13 Python
分享Pycharm中一些不为人知的技巧
Apr 03 Python
python 从csv读数据到mysql的实例
Jun 21 Python
python中单下划线_的常见用法总结
Jul 10 Python
Python 给某个文件名添加时间戳的方法
Oct 16 Python
Python 实现网课实时监控自动签到、打卡功能
Mar 12 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
Mar 18 Python
Python yield生成器和return对比代码实例
Apr 20 Python
Python日志处理模块logging用法解析
May 19 Python
python如何建立全零数组
Jul 19 Python
python实现web邮箱扫描的示例(附源码)
Mar 30 Python
手把手教你Python yLab的绘制折线图的画法
Oct 23 #Python
Python之Numpy的超实用基础详细教程
Oct 23 #Python
Python从列表推导到zip()函数的5种技巧总结
Oct 23 #Python
Python箱型图绘制与特征值获取过程解析
Oct 22 #Python
Python使用贪婪算法解决问题
Oct 22 #Python
python元组和字典的内建函数实例详解
Oct 22 #Python
Python List列表对象内置方法实例详解
Oct 22 #Python
You might like
drupal 代码实现URL重写
2011/05/04 PHP
9个PHP开发常用功能函数小结
2011/07/15 PHP
解析PHP生成静态html文件的三种方法
2013/06/18 PHP
Yii框架调试心得--在页面输出执行sql语句
2014/12/25 PHP
PHP读取zip文件的方法示例
2016/11/17 PHP
php实现的统计字数函数定义与使用示例
2017/07/26 PHP
通过ifame指向的页面高度调整iframe的高度
2006/10/05 Javascript
ie和firefox中img对象区别的困惑
2006/12/27 Javascript
JS判断元素为数字的奇异写法分享
2012/08/01 Javascript
jQuery 无限级菜单的简单实例
2014/02/21 Javascript
javascript模拟命名空间
2015/04/17 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
2015/10/23 Javascript
基于javascript实现动态显示当前系统时间
2016/01/28 Javascript
bootstrap table操作技巧分享
2017/02/15 Javascript
jQuery Json数据格式排版高亮插件json-viewer.js使用方法详解
2017/06/12 jQuery
使用vue-cli+webpack搭建vue开发环境的方法
2017/12/22 Javascript
JavaScript实现构造json数组的方法分析
2018/08/17 Javascript
js实现简易计算器小功能
2020/11/18 Javascript
二种python发送邮件实例讲解(python发邮件附件可以使用email模块实现)
2013/12/03 Python
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
python Celery定时任务的示例
2018/03/13 Python
python opencv旋转图像(保持图像不被裁减)
2018/07/26 Python
Python3随机漫步生成数据并绘制
2018/08/27 Python
Python 文本文件内容批量抽取实例
2018/12/10 Python
numpy ndarray 按条件筛选数组,关联筛选的例子
2019/11/26 Python
利用Python实现朋友圈中的九宫格图片效果
2020/09/03 Python
基于Python的接口自动化读写excel文件的方法
2021/01/15 Python
使用SVG实现提示框功能的示例代码
2020/06/05 HTML / CSS
Java中实现多态的机制
2015/08/09 面试题
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
电视节目策划方案
2014/05/16 职场文书
英语教育专业自荐信
2014/05/29 职场文书
租房安全协议书
2014/08/20 职场文书
诚信考试承诺书范文
2015/04/29 职场文书
小学英语课教学反思
2016/02/15 职场文书
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android