项目参照高老师的《视觉SLAM十四讲》进行实现,主要是为了巩固自己知识,代码仅供参考。
需要注意的是,代码opencv的版本是3.4.2.16(4版本的opencv太新了,好像不兼容),此外,在主函数里面,需要输入自己的图片哦!
import numpy as np
import cv2 as cv
def find_feature_matches(img_1, img_2):
"""寻找特征匹配的点
Args:
img_1: pass
img_2: pass
Returns:
kp1:
kp2:
good_match:
"""
orb = cv.ORB_create()
kp1 = orb.detect(img_1)
kp2 = orb.detect(img_2)
kp1, des1 = orb.compute(img_1, kp1)
kp2, des2 = orb.compute(img_2, kp2)
bf = cv.BFMatcher(cv.NORM_HAMMING)
matches = bf.match(des1, des2)
min_distance = matches[0].distance
max_distance = matches[0].distance
for x in matches:
if x.distance < min_distance:
min_distance = x.distance
if x.distance > max_distance:
max_distance = x.distance
print("Max dist:", max_distance)
print("Min dist:", min_distance)
good_match = []
for x in matches:
if x.distance <= max(2*min_distance, 30.0):
good_match.append(x)
return kp1, kp2, good_match
if __name__ == "__main__":
img1 = cv.imread("1.png")
img2 = cv.imread("2.png")
depth1 = cv.imread("1_depth.png", -1) # 读取深度图像要用-1
depth2 = cv.imread("2_depth.png", -1)
# 图像匹配
keypoints_1, keypoints_2, matches = find_feature_matches(img1, img2)
print("共计匹配点:", len(matches))
# 筛选特征点,只记匹配的点,参照上一博客的poes_estimation_2d2d(keypoint_1, keypoint_2, matches)函数
pts2 = []
pts1 = []
for i in range(int(len(matches))):
pts1.append(keypoints_1[matches[i].queryIdx].pt)
pts2.append(keypoints_2[matches[i].trainIdx].pt)
pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
# 建立3D点
# 深度图像为16位无符号数,单通道图像
K=[[520.9, 0, 325.1], [0, 521.0, 249.7], [0, 0, 1]]
K=np.array(K)
pts_3d = []
pts_2d = []
for i in range(pts1.shape[0]): # pts1.shape[0]: 匹配点总数 pts1.shape = (len(matches), 2)
p1 = pts1[i]
d1 = depth1[p1[1],p1[0]]/1000.0 # 深度距离 以5000为一个单位 高博的是1000.0
#print(d1)
if d1 == 0:
continue
p1 = (p1 - (K[0][2],K[1][2]))/(K[0][0],K[1][1])*d1 # 归一化坐标 根据深度单位转为实际坐标
pts_3d.append([p1[0], p1[1], d1])
pts_2d.append(pts2[i])
#
print("最终匹配数:", len(pts_3d))
pts_3d = np.float64(pts_3d)
pts_2d = np.float64(pts_2d)
print("3D点:")
print(pts_3d)
flag,R,t = cv.solvePnP(pts_3d,pts_2d,K,None)
R,Jacobian = cv.Rodrigues(R)
print("旋转矩阵R:\n", R)
print("平移矩阵t:\n", t)
最终输出的两个矩阵与上一篇的博客的结果有点区别,旋转矩阵基本上对上了,但是平移矩阵,都有差别,不管是与上一篇博客的还是与高博的