1. 简介

首先通过 cv2.ORB_create 创建ORB检测器 orb
然后通过 orb.detectAndCompute 检测两张图片获得ORB角点,
接着通过匹配器 cv2.BFMatcher 进行配对,
最后通过 cv2.findHomography 计算变换矩阵。


2. ORB角点检测匹配和偏移计算


2.1. 创建平移图片

首先我们先创建一个平移图片作为两个比较的图片

from cv2 import cv2
import numpy as np


# 读取图片文件
demo_file_path = 'img1.png'
img = cv2.imdecode(np.fromfile(demo_file_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
cv2.imshow('origin img', img)

# 平移变量
T_x, T_y = 10, 20

# 旋转变量 0°
angles = 0
sin_phi, cos_phi = np.sin(np.radians(angles)), np.cos(np.radians(angles))

# 构造仿射变换矩阵H 2*3
H = np.float32([[cos_phi, -sin_phi, T_x],
                [sin_phi, cos_phi, T_y]])
np.set_printoptions(suppress=True)
print(H)

# 仿射变换
new_img = cv2.warpAffine(img, H, (img.shape[1], img.shape[0]))

# 保存图片
cv2.imencode('.png', new_img)[1].tofile('img2.png')
cv2.imshow('new img', new_img)
cv2.waitKey(0)

平移x轴10个像素点,y轴20个像素点,其他不变,如下图所示:

在这里插入图片描述
仿射变换矩阵 H H H,这里纯平移,所以也是就平移矩阵,如下:

[[ 1. -0. 10.]
 [ 0.  1. 20.]]

关于透视变换参考:《OpenCV 透视变换》


2.2. ORB角点检测

import cv2
import numpy as np
 
# 读取两个连续图像
img1 = cv2.imread('img1.png')
img2 = cv2.imread('img2.png')
 
# 初始化ORB检测器
orb = cv2.ORB_create(nfeatures=500)

# 检测关键点和描述符
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

# 显示ORB角点
keypoints_img1 = cv2.drawKeypoints(img1, kp1, None, color=(0,255,0), flags=0)
keypoints_img2 = cv2.drawKeypoints(img2, kp2, None, color=(0,255,0), flags=0)
cv2.imshow('Keypoints Image1', keypoints_img1)
cv2.imshow('Keypoints Image2', keypoints_img2)

首先通过 cv2.ORB_create 创建ORB检测器 orb
然后通过 orb.detectAndCompute 检测两张图片获得ORB角点
然后通过 cv2.drawKeypoints 将角点可视化,如下图:

在这里插入图片描述


2.3. ORB角点匹配

# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)

# 根据匹配结果排序,取较优的50个
matches = sorted(matches, key = lambda x:x.distance)[:50]
 
# 显示匹配关系
matches_img = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=2)
cv2.imshow('Matches Image', matches_img)

通过 cv2.BFMatcher 创建匹配器,其中有两个参数:

  1. normType:它指定要使用的距离量度。
    默认是 cv2.NORM_L2,对于SIFT,SURF 效果较佳
    对于二进制字符串的描述子,比如ORB,BRIEF,BRISK等,应该用cv2.NORM_HAMMING(汉明距离度量)
    使用,如果ORB检测器的 WTA_K 设置 3或者4,应该用cv2.NORM_HAMMING2

  2. crossCheck:匹配器为每个查询描述符找到 k 个距离最近的匹配描述符;
    默认为 False,为 True 时,只返回满足交叉验证条件的匹配结果。

在这里插入图片描述


2.4. 计算变换矩阵

# 提取匹配点
src_pts = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1,1,2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1,1,2)
 
# 计算变换矩阵
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()  # 可用于cv2.drawMatches可视化匹配关系的掩模
np.set_printoptions(suppress=True)
print(H)

# 可视化变换结果
offset_img = cv2.warpPerspective(img1, H, (img1.shape[1], img1.shape[0]))
cv2.imshow('Offset Image', offset_img)

cv2.waitKey(0)
cv2.destroyAllWindows()

提取匹配点两个图片的src_ptsdst_pts,通过 cv2.findHomography 计算变换矩阵
可以看到计算出来的透视变换矩阵可以看到结果为x轴平移,与实际一致

[[ 1.  0. 10.]
 [-0.  1. 20.]
 [-0.  0.  1.]]

那么,显示变换结果也将一致,如下图:

在这里插入图片描述


谢谢

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部