在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中函数的多种格式和使用实例及小技巧
Apr 13 Python
python计算时间差的方法
May 20 Python
解析Python编程中的包结构
Oct 25 Python
python使用正则表达式来获取文件名的前缀方法
Oct 21 Python
关于python之字典的嵌套,递归调用方法
Jan 21 Python
在python中将list分段并保存为array类型的方法
Jul 15 Python
Python 使用matplotlib模块模拟掷骰子
Aug 08 Python
如何使用python实现模拟鼠标点击
Jan 06 Python
Python字典添加,删除,查询等相关操作方法详解
Feb 07 Python
详解python datetime模块
Aug 17 Python
python周期任务调度工具Schedule使用详解
Nov 23 Python
Python中的turtle画箭头,矩形,五角星
Mar 16 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
终于听上了直流胆调频
2021/03/02 无线电
3.从实例开始
2006/10/09 PHP
解析zend studio中直接导入svn中的项目的方法步骤
2013/06/21 PHP
解析php中var_dump,var_export,print_r三个函数的区别
2013/06/21 PHP
php字符串比较函数用法小结(strcmp,strcasecmp,strnatcmp及strnatcasecmp)
2016/07/18 PHP
php die()与exit()的区别实例详解
2016/12/03 PHP
apache集成php7.3.5的详细步骤
2019/06/20 PHP
php判断IP地址是否在多个IP段内
2020/08/18 PHP
在iframe里的页面编写js,实现在父窗口上创建动画效果展开和收缩的div(不变动iframe父窗口代码)
2011/12/20 Javascript
js网页实时倒计时精确到秒级
2014/02/10 Javascript
JQuery 图片滚动轮播示例代码
2014/03/24 Javascript
javascript Array 数组常用方法
2015/04/05 Javascript
让JavaScript中setTimeout支持链式操作的方法
2015/06/19 Javascript
Javascript类型系统之String字符串类型详解
2016/06/21 Javascript
Angular2 (RC5) 路由与导航详解
2016/09/21 Javascript
AngularJS中的按需加载ocLazyLoad示例
2017/01/11 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
Nuxt项目支持eslint+pritter+typescript的实现
2019/05/20 Javascript
微信小程序订阅消息(java后端实现)开发
2020/06/01 Javascript
Node.js web 应用如何封装到Docker容器中
2020/09/01 Javascript
python计算两个地址之间的距离方法
2018/06/09 Python
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
Python使用googletrans报错的解决方法
2018/09/25 Python
python3对拉勾数据进行可视化分析的方法详解
2019/04/03 Python
Python Web版语音合成实例详解
2019/07/16 Python
Python enumerate内置库用法解析
2020/02/24 Python
selenium与xpath之获取指定位置的元素的实现
2021/01/26 Python
Web时代变迁及html5与html4的区别
2016/01/06 HTML / CSS
新东网科技Java笔试题
2012/07/13 面试题
职业规划实施方案
2014/06/10 职场文书
我的1919观后感
2015/06/03 职场文书
golang通过递归遍历生成树状结构的操作
2021/04/28 Golang
CSS基础详解
2021/10/16 HTML / CSS
苹果电脑mac os中货币符号快捷输入
2022/02/17 杂记
GTX1650super好不好 gtx1650super显卡属于什么级别
2022/04/08 数码科技
Golang map映射的用法
2022/04/22 Golang