SIFT算法python实现图像拼接
目录
SIFT算法.... 2
1.读入图片并转化为灰度图... 2
2.创建SIFT对象.... 2
求解特征点和特征向量.... 2
3.构造BFMacher对象... 2
4.用knnMatch方法进行关键点多点匹配.... 2
5.去除不可靠匹配.... 3
6.寻得可靠匹配点并转换类型.... 3
7.求解转换矩阵.... 4
8.图像空间变换.... 4
9.图像拼接.... 5
10.显示结果.... 5
left = cv2.imread("left.png")
right = cv2.imread("right.png")
gray1 = cv2.cvtColor(left, cv2.THRESH_BINARY)
gray2 = cv2.cvtColor(right, cv2.THRESH_BINARY)
sift = cv2.xfeatures2d.SIFT_create()
创建对象时不需要传递参数
kpsA, dpA = sift.detectAndCompute(gray1, None)
kpsB, dpB = sift.detectAndCompute(gray2, None)
有两个必须的参数,第一个是求解特征点和特征向量的图像。第二个参数决定是否对特定区域求解,传入一个mask。
返回值kps是对图像求解的特征点,是一个一维向量,其中每一个元素属于keypoint类型。dp是与kps对性的特征向量,也是一个列表,其中每一个元素是长度为128的向量.
brute force蛮力匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(dpA, dpB, k=2)
knnMatch有三个参数,前两个是需要进行匹配的图像的特征向量,k为需要匹配的点的对数。
返回值是一个列表,其中每个元素也是一个列表,列表中有两个元素,为DMatch类型
(图片截屏自blbl课程视屏)
good_matches = []
for m in matches:
if len(m) == 2 and m[0].distance < 0.4 * m[1].distance:
good_matches.append((m[0].queryIdx, m[0].trainIdx))
新建一个空列表
遍历matches,如果第一对点的欧氏距离小于k倍第二对点的欧氏距离则说明第一对点匹配可靠,将这对点的索引号追加到good_matches
kps1 = np.float32([kp.pt for kp in kpsA])
kps2 = np.float32([kp.pt for kp in kpsB]
将keypoint的pt属性(即关键点的坐标)赋值给kps
kps1 = np.float32([kps1[a[0]] for a in good_matches])
kps2 = np.float32([kps2[a[1]] for a in good_matches]
将根据good_matches匹配好的序号,将kps1和kps2对应排序
M, status = cv2.findHomography(kps2, kps1, cv2.RANSAC, 4.0)
findHomography的参数,前两个是对应关键点的坐标,第三个是求解方法,第四个是将点对视为内点的最大允许重投影错误阈值(仅用于RANSAC和RHO方法)。
返回值M为变换矩阵。
result = cv2.warpPerspective(right, M, (left.shape[1] + right.shape[1], right.shape[0]))
warpPerspective的参数中,第一个为要变换的图像,第二个为变换矩阵,第三个为变换后图像的长,第四个为变换后图像的高。
result[0:left.shape[0], 0:left.shape[1]] = left
将变换后的图像对应要拼接原图像的地方用原图像覆盖。
cv2.imshow("left", left)
cv2.imshow("right", right)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()