目录
3.1 单应性变换
单应性变换是将一个平面内的点映射到另一个平面内的二维投影变换。
实验代码如下:
import cv2
import numpy as np
# 加载图像
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')
# 转为灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建SIFT特征检测器
sift = cv2.SIFT_create()
# 检测关键点和计算描述子
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)
# 使用BFMatcher进行特征匹配
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
# 应用比率测试进行过滤
good_matches = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good_matches.append(m)
# 提取匹配点坐标
pts1 = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
pts2 = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
# 计算单应性矩阵
H, mask = cv2.findHomography(pts1, pts2, cv2.RANSAC)
# 应用单应性变换
height, width, channels = img2.shape
warped_img = cv2.warpPerspective(img1, H, (width, height))
# 显示结果
cv2.imshow('Warped Image', warped_img)
cv2.imshow('Original Image', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
分析:
-
特征检测与描述:使用SIFT检测两幅图像中的特征点,并计算它们的描述子。这一步为后续的特征匹配做准备。
-
特征匹配:通过BFMatcher和比率测试筛选出最佳匹配对,确保匹配的可靠性。
-
单应性矩阵计算:使用RANSAC算法计算单应性矩阵(Homography Matrix),该矩阵用于描述从一幅图像到另一幅图像的透视变换。
-
应用单应性变换:利用
cv2.warpPerspective
函数对原始图像应用计算出的单应性矩阵,进行透视变换,使得图像对齐到目标图像的视角。 -
结果可视化:通过显示变换后的图像和目标图像,直观评估图像配准的效果。
结果:
3.1.1 直接线性变换算法
DLT(Direct Linear Transformation,直接线性变换)是给定4个或者更多对应点对矩阵,来计算单应性矩阵 H 的算法。
import numpy as np
import cv2
import matplotlib.pyplot as plt
def dlt(points1, points2):
"""
直接线性变换(DLT)算法计算单应性矩阵
"""
A = []
for p1, p2 in zip(points1, points2):
x1, y1 = p1
x2, y2 = p2
A.append([-x1, -y1, -1, 0, 0, 0, x2*x1, x2*y1, x2])
A.append([0, 0, 0, -x1, -y1, -1, y2*x1, y2*y1, y2])
A = np.array(A)
_, _, Vt = np.linalg.svd(A)
H = Vt[-1].reshape(3, 3)
return H
# 加载图像
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')
# 转为灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建SIFT特征检测器
sift = cv2.SIFT_create()
# 检测关键点和计算描述子
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)
# 使用BFMatcher进行特征匹配
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
# 应用比率测试进行过滤
good_matches = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good_matches.append(m)
# 提取匹配点坐标
pts1 = np.float32([kp1[m.queryIdx].pt for m in good_matches])
pts2 = np.float32([kp2[m.trainIdx].pt for m in good_matches])
# 计算单应性矩阵
H = dlt(pts1, pts2)
# 应用单应性变换
height, width, channels = img2.shape
warped_img = cv2.warpPerspective(img1, H, (width, height))
# 显示结果
plt.subplot(1, 2, 1)
plt.title('Warped Image')
plt.imshow(cv2.cvtColor(warped_img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.title('Original Image')
plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
plt.show()
分析:
-
特征检测与描述:使用SIFT提取图像中的特征点及其描述子,这为匹配和后续的单应性计算提供了基础数据。
-
特征匹配:通过BFMatcher和比率测试筛选出最佳的特征匹配对,确保匹配的准确性和可靠性。
-
DLT算法:通过
dlt
函数计算单应性矩阵,该矩阵描述了从一幅图像到另一幅图像的透视变换。算法通过构建一个线性方程组并使用SVD求解得到单应性矩阵。 -
应用单应性变换:利用计算得到的单应性矩阵对图像进行透视变换,使得源图像对齐到目标图像的视角。
-
结果可视化