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

yipeiwu_com5年前Python基础

前面已经学习特征查找和对应匹配,接着下来在特征匹配之后,再使用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里使用特征匹配和单映射变换的代码详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对【听图阁-专注于Python设计】网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

Python处理RSS、ATOM模块FEEDPARSER介绍

由于Google reader的关闭,这段时间接触rss的东西相对多很多。试过qq的reader,不怎么样,阅读速度没有,是否阅读的标记也没有。其他网站的不想用,又要多注册账户。 找到p...

Python调用C# Com dll组件实战教程

Python调用C# Com dll组件实战教程

之前公司有套C# AES加解密方案,但是方案加密用的是Rijndael类,而非AES的四种模式(ECB、CBC、CFB、OFB,这四种用的是RijndaelManaged类),Pytho...

Python中计算三角函数之cos()方法的使用简介

 cos()方法返回x弧度的余弦值。 语法 以下是cos()方法的语法: cos(x) 注意:此函数是无法直接访问的,所以我们需要导入math模块,然后需要用math的静态对象...

Python数据类型之List列表实例详解

本文实例讲述了Python数据类型之List列表。分享给大家供大家参考,具体如下: list列表 1.概述: 通过之前的学习,我们知道变量可以存储数据,但是一个变量只能存储一个数据,现...

Python探索之静态方法和类方法的区别详解

面相对象程序设计中,类方法和静态方法是经常用到的两个术语。 逻辑上讲:类方法是只能由类名调用;静态方法可以由类名或对象名进行调用。 python staticmethod and cla...