我需要一个使用harris算法实现三幅图片全景图像拼接的代码
时间: 2024-05-15 09:14:11 浏览: 88
好的,这里给你提供一个使用Harris角点检测与SIFT特征匹配实现三幅图片全景图像拼接的Python代码。首先需要安装OpenCV、numpy和matplotlib库。
```python
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 读取三幅图片
img1 = cv2.imread('img1.jpg')
img2 = cv2.imread('img2.jpg')
img3 = cv2.imread('img3.jpg')
# 将三幅图片转换为灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
gray3 = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY)
# 使用Harris角点检测算法检测图像中的角点
corners1 = cv2.cornerHarris(gray1, 2, 3, 0.04)
corners2 = cv2.cornerHarris(gray2, 2, 3, 0.04)
corners3 = cv2.cornerHarris(gray3, 2, 3, 0.04)
# 对角点进行非极大值抑制,得到角点的坐标
corners1 = cv2.dilate(corners1, None)
corners2 = cv2.dilate(corners2, None)
corners3 = cv2.dilate(corners3, None)
threshold = 0.01 * np.max(corners1)
corners1_img = np.copy(img1)
corners2_img = np.copy(img2)
corners3_img = np.copy(img3)
for i in range(corners1.shape[0]):
for j in range(corners1.shape[1]):
if corners1[i,j] > threshold:
cv2.circle(corners1_img, (j,i), 3, (0,255,0), -1)
for i in range(corners2.shape[0]):
for j in range(corners2.shape[1]):
if corners2[i,j] > threshold:
cv2.circle(corners2_img, (j,i), 3, (0,255,0), -1)
for i in range(corners3.shape[0]):
for j in range(corners3.shape[1]):
if corners3[i,j] > threshold:
cv2.circle(corners3_img, (j,i), 3, (0,255,0), -1)
# 将角点进行SIFT特征匹配
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)
kp3, des3 = sift.detectAndCompute(gray3, None)
bf = cv2.BFMatcher()
matches1 = bf.knnMatch(des1, des2, k=2)
matches2 = bf.knnMatch(des2, des3, k=2)
good_matches1 = []
for m,n in matches1:
if m.distance < 0.75 * n.distance:
good_matches1.append([m])
good_matches2 = []
for m,n in matches2:
if m.distance < 0.75 * n.distance:
good_matches2.append([m])
src_pts1 = np.float32([kp1[m[0].queryIdx].pt for m in good_matches1]).reshape(-1,1,2)
dst_pts1 = np.float32([kp2[m[0].trainIdx].pt for m in good_matches1]).reshape(-1,1,2)
src_pts2 = np.float32([kp2[m[0].queryIdx].pt for m in good_matches2]).reshape(-1,1,2)
dst_pts2 = np.float32([kp3[m[0].trainIdx].pt for m in good_matches2]).reshape(-1,1,2)
# 使用RANSAC算法进行图像拼接
H1, mask1 = cv2.findHomography(src_pts1, dst_pts1, cv2.RANSAC, 5.0)
H2, mask2 = cv2.findHomography(src_pts2, dst_pts2, cv2.RANSAC, 5.0)
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
h3, w3 = img3.shape[:2]
# 将图像1和图像2进行拼接
pts1 = np.float32([[0,0], [0,h1-1], [w1-1,h1-1], [w1-1,0]]).reshape(-1,1,2)
pts2 = np.float32([[0,0], [0,h2-1], [w2-1,h2-1], [w2-1,0]]).reshape(-1,1,2)
dst1 = cv2.perspectiveTransform(pts1, H1)
dst2 = cv2.perspectiveTransform(pts2, H1)
# 将图像2和图像3进行拼接
pts3 = np.float32([[0,0], [0,h2-1], [w2-1,h2-1], [w2-1,0]]).reshape(-1,1,2)
pts4 = np.float32([[0,0], [0,h3-1], [w3-1,h3-1], [w3-1,0]]).reshape(-1,1,2)
dst3 = cv2.perspectiveTransform(pts3, H2)
dst4 = cv2.perspectiveTransform(pts4, H2)
# 计算全景图像的大小
x_min = min(np.min(dst1[:,:,0]), np.min(dst2[:,:,0]), np.min(dst3[:,:,0]), np.min(dst4[:,:,0]))
x_max = max(np.max(dst1[:,:,0]), np.max(dst2[:,:,0]), np.max(dst3[:,:,0]), np.max(dst4[:,:,0]))
y_min = min(np.min(dst1[:,:,1]), np.min(dst2[:,:,1]), np.min(dst3[:,:,1]), np.min(dst4[:,:,1]))
y_max = max(np.max(dst1[:,:,1]), np.max(dst2[:,:,1]), np.max(dst3[:,:,1]), np.max(dst4[:,:,1]))
x_offset = abs(int(x_min))
y_offset = abs(int(y_min))
width = int(x_max - x_min)
height = int(y_max - y_min)
# 将图像进行平移,使其全部在全景图像内
H1_translation = np.array([[1, 0, x_offset], [0, 1, y_offset], [0, 0, 1]])
H2_translation = np.array([[1, 0, x_offset-w1], [0, 1, y_offset], [0, 0, 1]])
img1_translation = cv2.warpPerspective(img1, H1_translation, (width, height))
img2_translation = cv2.warpPerspective(img2, H1.dot(H2_translation), (width, height))
img3_translation = cv2.warpPerspective(img3, H1.dot(H2.dot(H2_translation)), (width, height))
# 将三幅图像拼接为全景图像
panorama = np.zeros((height+2*y_offset, width+2*x_offset, 3), dtype='uint8')
panorama[y_offset:y_offset+height, x_offset:x_offset+width] = img1_translation
for i in range(panorama.shape[0]):
for j in range(panorama.shape[1]):
if np.all(img2_translation[i,j] != 0):
panorama[i,j] = img2_translation[i,j]
for i in range(panorama.shape[0]):
for j in range(panorama.shape[1]):
if np.all(img3_translation[i,j] != 0):
panorama[i,j] = img3_translation[i,j]
# 显示全景图像
plt.imshow(cv2.cvtColor(panorama, cv2.COLOR_BGR2RGB))
plt.show()
```
注意:这个代码只是一个简单的示例,可能无法处理所有的情况。在实际应用中,可能需要进行更多的调整和优化。
阅读全文