OpenCV Python——图像查找(特征匹配 + 单应性矩阵)

发布于:2025-08-16 ⋅ 阅读:(18) ⋅ 点赞:(0)


P87 11

1 图像查找(单应性矩阵)

特征匹配作为输入,获得单应性矩阵
在这里插入图片描述

X在img1和img2中的成像分别为x,x'

图中H即为单应性矩阵
在这里插入图片描述

2 单应性矩阵 应用举例

获取一个矩阵,通过与图像1就算可以得到图像2对应点的位置;
图像二通过计算可以得到点原始位置,同样图像一也可以经过计算得到点原始位置;

自动转正

在这里插入图片描述
更换广告牌中的内容
在这里插入图片描述

3 单应性矩阵 代码示例

在一节FLANN特征匹配的基础上增加了,单应性矩阵、透视变换、框图

#获取的单应性矩阵
#srcPts从匹配点good中获取,每次遍历都可以从kp1[m.queryIdx]中获取一个关键点
#关键点需要转成浮点型
#对获取到的关键点要重新变换reshape(-1, 1, 2),x值随意,y值1,z值2,即无数行,每行一个元素,每个元素有2个子元素
#queryIdx,trainIdx分别是第一幅图,第二幅图的描述子索引值
if len(good) >= 4:#单应性矩阵要求匹配点要大于等于4
    srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)#原关键点
    dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)#目标关键点
    #单应性矩阵
    H, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)#cv2.RANSAC对错误匹配点过滤,阈值1~10,这里是5
    
    #透视变换
    #获取要搜索的图的四个角点(左上,左下,右下,右上),同样需要转成浮点型,然后reshape
    h, w = img1.shape[:2]
    pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    dst = cv2.perspectiveTransform(pts, H)
    #多边形绘制,将找到的子图在原图中框出来吧
    cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))#目标图,32位整形,TRUE封口,
else:
    print('the number of good is less than 4.')
    exit()

效果如下:

在这里插入图片描述

完整代码

import cv2
import numpy as np

#读文件
img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')


#灰度化
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)


#创建sift对象                                                       
sift= cv2.xfeatures2d.SIFT_create()

#进行检测关键点,同时计算描述子
kp1 ,des1= sift.detectAndCompute(gray1, None)#掩码设置为NONE,即对整张图检测
kp2 ,des2= sift.detectAndCompute(gray2, None)#掩码设置为NONE,即对整张图检测

#创建flann匹配器
index_params=dict(algorithm=1,tree=5)
search_params=dict(checks=50)

flann=cv2.FlannBasedMatcher(index_params,search_params)

#对描述子进行特征匹配
matches=flann.knnMatch(des1,des2,k=2)

#对匹配点优化过滤
good=[]
for i,(m,n) in enumerate(matches):#对img1,img2中的匹配点进行遍历
    if m.distance < 0.7* n.distance:#越小越精准
        good.append(m)

#获取的单应性矩阵
#srcPts从匹配点good中获取,每次遍历都可以从kp1[m.queryIdx]中获取一个关键点
#关键点需要转成浮点型
#对获取到的关键点要重新变换reshape(-1, 1, 2),x值随意,y值1,z值2,即无数行,每行一个元素,每个元素有2个子元素
#queryIdx,trainIdx分别是第一幅图,第二幅图的描述子索引值
if len(good) >= 4:#单应性矩阵要求匹配点要大于等于4
    srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)#原关键点
    dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)#目标关键点
    #单应性矩阵
    H, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)#cv2.RANSAC对错误匹配点过滤,阈值1~10,这里是5
    
    #透视变换
    #获取要搜索的图的四个角点(左上,左下,右下,右上),同样需要转成浮点型,然后reshape
    h, w = img1.shape[:2]
    pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    dst = cv2.perspectiveTransform(pts, H)
    #多边形绘制,将找到的子图在原图中框出来吧
    cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))#目标图,32位整形,TRUE封口,
else:
    print('the number of good is less than 4.')
    exit()

#绘制匹配结果
img3=cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)

cv2.imshow('img3', img3)
cv2.waitKey(0)

网站公告

今日签到

点亮在社区的每一天
去签到