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

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

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

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

参数详解:

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,以便于反向投影错误率达到最小。

演示使用的例子如下:

#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里使用特征匹配和单映射变换的代码详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • C#中OpenCvSharp 通过特征点匹配图片的方法

    现在的手游基本都是重复操作,一个动作要等好久,结束之后继续另一个动作.很麻烦,所以动起了自己写一个游戏辅助的心思. 这个辅助本身没什么难度,就是通过不断的截图,然后从这个截图中找出预先截好的能代表相应动作的按钮或者触发条件的小图. 找到之后获取该子区域的左上角坐标,然后通过windows API调用鼠标或者键盘做操作就行了. 这里面最难的也就是找图了,因为要精准找图,而且最好能适应不同的分辨率下找图,所以在模板匹配的基础上,就有了SIFT和SURF的特征点找图方式. 在写的过程中查找资料,大都是

  • 浅谈Python Opencv中gamma变换的使用详解

    伽马变换就是用来图像增强,其提升了暗部细节,简单来说就是通过非线性变换,让图像从暴光强度的线性响应变得更接近人眼感受的响应,即将漂白(相机曝光)或过暗(曝光不足)的图片,进行矫正. 伽马变换的基本形式如下: 大于1时,对图像的灰度分布直方图具有拉伸作用(使灰度向高灰度值延展),而小于1时,对图像的灰度分布直方图具有收缩作用(是使灰度向低灰度值方向靠拢). #分道计算每个通道的直方图 img0 = cv2.imread('12.jpg') hist_b = cv2.calcHist([img0],

  • python opencv 图像尺寸变换方法

    利用Python OpenCV中的 cv.Resize(源,目标,变换方法)就可以实现变换为想要的尺寸了 源文件:就不用说了 目标:你可以对图像进行倍数的放大和缩小 也可以直接的输入尺寸大小 变换的方法: CV_INTER_NN - 最近邻插值, CV_INTER_LINEAR - 双线性插值 (缺省使用) CV_INTER_AREA - 使用象素关系重采样.当图像缩小时候,该方法可以避免波纹出现.当图像放大时,类似于 CV_INTER_NN 方法.. CV_INTER_CUBIC - 立方插值

  • python opencv实现任意角度的透视变换实例代码

    本文主要分享的是一则python+opencv实现任意角度的透视变换的实例,具体如下: # -*- coding:utf-8 -*- import cv2 import numpy as np def rad(x): return x * np.pi / 180 img = cv2.imread("6.jfif") cv2.imshow("original", img) # 扩展图像,保证内容不超出可视范围 img = cv2.copyMakeBorder(img,

  • opencv python 傅里叶变换的使用

    理论 傅立叶变换用于分析各种滤波器的频率特性,对于图像,2D离散傅里叶变换(DFT)用于找到频域.快速傅里叶变换(FFT)的快速算法用于计算DFT. 于一个正弦信号,x(t)=Asin(2πft),我们可以说 f 是信号的频率,如果它的频率域被接受,我们可以看到 f 的峰值.如果信号被采样来形成一个离散信号,我们得到相同的频率域,但是在[−π,π] or [0,2π]范围内是周期性的 (or [0,N] for N-point DFT). 可以将图像视为在两个方向上采样的信号.因此,在X和Y方向

  • 详解opencv Python特征检测及K-最近邻匹配

    鉴于即将启程旅行,先上传篇简单的图像检索介绍,与各位一起学习opencv的同学共勉 一.特征检测 图片的特征主要分为角点,斑点,边,脊向等,都是常用特征检测算法所检测到的图像特征· 1.Harris角点检测 先将图片转换为灰度模式,再使用以下函数检测图片的角点特征: dst=cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]]) 重点关注第三个参数,这里使用了Sobel算子,简单来说,其取为3-31间的奇数,定义了角点检测的

  • opencv 做人脸识别 opencv 人脸匹配分析

    机器学习 机器学习的目的是把数据转换成信息. 机器学习通过从数据里提取规则或模式来把数据转成信息. 人脸识别 人脸识别通过级联分类器对特征的分级筛选来确定是否是人脸. 每个节点的正确识别率很高,但正确拒绝率很低. 任一节点判断没有人脸特征则结束运算,宣布不是人脸. 全部节点通过,则宣布是人脸. 工业上,常用人脸识别技术来识别物体. 对图片进行识别 复制代码 代码如下: #include "opencv2/core/core.hpp" #include "opencv2/obj

  • OpenCV 模板匹配

    最近小编实现一个微信小程序「跳一跳」的自动化. 主要涉及到了OpenCV的模板匹配和边缘检测技术,以及Android开发调试工具ADB. 如果放在一起说,感觉内容有些多. 所以,分三期来讲,也能多了解一些东西. 首先介绍模板匹配,然后边缘检测,最后结合ADB实现「跳一跳」自动化. 游戏虽然过时了,但是拿来练练手还是不错的. 编程就该是快乐的,哈哈. / 01 / 模板匹配 模板匹配,就是在整个图像区域里发现与给定子图像相匹配的小块区域. 这里需要一个模板图像(给定的子图像)和一个待检测的图像(原

  • Java+opencv3.2.0实现模板匹配

    模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术. 函数:Imgproc.matchTemplate(Mat image, Mat templ, Mat result, int method) 参数说明: image:源图像 templ:模板图像 result:比较结果 method:匹配算法 匹配算法: TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配:最好的匹配值为0:匹配越差,匹配值越大. TM_CCORR 相关匹配法:该方法采用乘法操作:数值越大表明匹配

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

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

  • 第七篇Bootstrap表单布局实例代码详解(三种表单布局)

    Bootstrap提供了三种表单布局:垂直表单,内联表单和水平表单.下面逐一给大家介绍,有兴趣的朋友一起学习吧. 创建垂直或基本表单: •·向父 <form> 元素添加 role="form". •·把标签和控件放在一个带有 class .form-group 的 <div> 中.这是获取最佳间距所必需的. •·向所有的文本元素 <input>.<textarea> 和 <select> 添加 class .form-cont

  • Vue.js实现可配置的登录表单代码详解

    表单是后台项目业务中的常用组件,这次重构了登录功能以满足登录方式可配置的需求,在此记录和分享一下. 业务场景 在之前,项目只支持手机号+密码登录,前端是直接把表单写死的,后来有客户希望能支持验证码登录,有的客户还希望能有手机号+验证码+密码的登录方式-所以登录方式的灵活性需要可配置的表单支持,于是我把登录组件做了拆分. 以表单元素为粒度,分离出了手机号.密码.短信验证码这几个组件,它们内部都有自己的表单验证方法,通过组合可以快速完成登录.注册.找回密码等表单组件.高内聚低耦合.高内聚低耦合-跟着

  • Python OpenCV特征检测之特征匹配方式详解

    目录 前言  一.暴力匹配器 二.FLANN匹配器 前言  获得图像的关键点后,可通过计算得到关键点的描述符.关键点描述符可用于图像的特征匹配.通常,在计算图A是否包含图B的特征区域时,将图A称做训练图像,将图B称为查询图像.图A的关键点描述符称为训练描述符,图B的关键点描述符称为查询描述符. 一.暴力匹配器 暴力匹配器使用描述符进行特征比较.在比较时,暴力匹配器首先在查询描述符中取一个关键点的描述符,将其与训练描述符中的所有关键点描述符进行比较,每次比较后会给出一个距离值,距离最小的值对应最佳

  • 表单验证正则表达式实例代码详解

    表单验证正则表达式具体内容如下所示: 首先给大家解释一些符号相关的意义 1.  /^$/ 这个是个通用的格式. ^ 匹配输入字符串的开始位置:$匹配输入字符串的结束位置 2. 里面输入需要实现的功能. * 匹配前面的子表达式零次或多次:        + 匹配前面的子表达式一次或多次:        ?匹配前面的子表达式零次或一次:        \d  匹配一个数字字符,等价于[0-9] 下面通过一段代码给大家分析表单验证正则表达式,具体代码如下: <!DOCTYPE html> <h

  • Asp.Net MVC4通过id更新表单内容的思路详解

    用户需求是:一个表单一旦创建完,其中大部分的字段便不可再编辑.只能编辑其中部分字段. 而不可编辑是通过对input输入框设置disabled属性实现的,那么这时候直接向数据库中submit表单中的内容就会报错,因为有些不能为null的字段由于disabled属性根本无法在前端被获取而后更新至数据库. 有下面两种思路: 1.通过创建隐藏表单,为每一个disabled控件分别创建一个隐藏控件,但是这样的问题是工作量太大(如果表单有一千个属性,你懂的) 2.通过获取该表单在数据库中的id,把该id和可

  • java 设计模式之单例的实例详解

    java 设计模式之单例的实例详解 设计模式思想 什么是设计模式:我作为初学者,今天第一次正式学习设计模式,我觉得对与理解什么是设计模式很重要,那么什么是设计模式呢? 设计模式:解决问题的一种行之有效的思想. 设计模式:用于解决特定环境下.重复出现的特定问题的解决方案 我的理解是前人在软件设计的时候碰到了一类问题,他们总结出了一套行之有效,并且经过验证的解决方案. 设计模式的优点: 1.设计模式都是一些相对优秀的解决方案,很多问题都是典型的.有代表性的问题,学习设计模式,我们就不用自己从头来解决

  • layui lay-verify form表单自定义验证规则详解

    官方文档详见:https://www.layui.com/doc/modules/form.html#verify 虽然layui的官方文档已经是写的比较详细,但是初次使用的时候总会懵一下,这里纪录一下lay-verify自定义验证规则的时候到底放哪. html: <input type="text" lay-verify="digital" placeholder="请输入数字"> <button type="but

  • C++单例类模板详解

    单例类 描述 指在整个系统生命期中,一个类最多只能有一个实例(instance)存在,使得该实例的唯一性(实例是指一个对象指针)  , 比如:统计在线人数 在单例类里,又分为了懒汉式和饿汉式,它们的区别在于创建实例的时间不同: 懒汉式 : 指代码运行后,实例并不存在,只有当需要时,才去创建实例(适用于单线程) 饿汉式 : 指代码一运行,实例已经存在,当时需要时,直接去调用即可(适用于多线程) 用法 将构造函数的访问属性设置为private, 提供一个GetInstance()静态成员函数,只能供

  • 对layui中表单元素的使用详解

    首先不管是单选框还是复选框或者是下拉框,都要在你写的标签外面套一层div或者是form标签,如: <div class="layui-input-block"> <input type="radio" name="sex" value="0" title="男"> </div>,class属性是固定写法. 这样写好了以后,你如果是写在静态页面,这样式可以看见效果,如果写在

随机推荐