十五天掌握OpenCV——使用特征匹配和单应性查找对象

魏老师学生——Cecil:学习OpenCV-机器视觉之旅

  • 原理
    • 代码演示

Aim:联合使用特征提取和calib3d模块中的findHomography在复杂图像中查找已知对象。

原理

cv2.findHomography() : 在目标图像中准确找到查询对象。
先将两幅图像的特征点传给函数cv2.findHomography() ,函数会找到对象的透视图变换。再使用cv2.perspectiveTransform() 找到对象。至少4个正确点才能找到变换!
为了避免匹配过程出现错误,算法使用RANSAC和LEAST_MEDIAN。好的匹配所提供的正确估计称为inliers,剩下称为outliers。
cv2.findHomography() 返回一个掩模,掩模确定inlier点和outlier点。

代码演示

先在图像中找到SIFT特征点,再使用比值测试找到最佳匹配。

#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt

MIN_MATCH_COUNT=10 #只有存在10个以上匹配时才去查找目标,否则报警。
"""匹配足够时,提取两幅图中匹配点的坐标。把坐标传入到函数
计算透视变换。找到3×3的变换矩阵后就可以使用它将查询图像的
四个顶点变换到目标图像去,再绘制出来。"""
img1=cv2.imread('./image2/mario.jpg',0)
img2=cv2.imread('./image2/coin.jpg',0)

sift=cv2.SIFT()

kp1,des1=sift.detectAndCompute(img1,None) #找到关键点和SIFT描述符
kp2,des2=sift.detectAndCompute(img2,None)

FLANN_INDEX_KDTREE=0
index_params=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
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)
    """上面函数第三个参数用来计算单应性矩阵,有下列几种方法:
    0 使用所有点,为常规方法。
    CV_RANSAC 基于RANSAC的鲁棒方法
    CV_LMEDS 最小中值稳健法
    第四个参数取值范围1-10,是个阈值,是原图像的点经过变换后点与目标图像上对应点的误差。
    超过误差就是outliers,返回值的M是变换矩阵。"""
    matchesMask=mask.ravel().tolist()
    h,w=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)
    #使用得到的变换矩阵对原图的四个角变换,获得在目标图像上对应的坐标
    cv2.polylines(img2,[np.int32(dst)],True,255,10,cv2.LINE_AA)
else:
    print("not enough matches are found - %d%d" % (len(good),MIN_MATCH_COUNT))
    matchesMask=None

#最后绘制inliers(成功找到目标对象)或者匹配的关键点(如果失败)
draw_params=dict(matchColor=(0,255,0),
                 singlePointColor=None,
                 matchesMask=matchesMask,#只绘出inliers
                 flags=2)
img3=cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3)
plt.show()```

你可能感兴趣的:(机器视觉)