SIFT算法:图像拼接的"智能胶水"

365万博首页 2026-02-23 11:15:22 admin 访问量: 5718 评分: 458
SIFT算法:图像拼接的

下面是完整的SIFT图像拼接Python代码,包含了羽化过渡融合优化。你可以复制这段代码,保存为sift_stitching.py,然后运行它来体验图像拼接的魔力!

💡 提示:确保你已经安装了必要的库:pip install opencv-python numpy matplotlib

import cv2

import numpy as np

import matplotlib.pyplot as plt

def feather_blend(image1, image2_transformed, width, height):

# 创建羽化掩码

# 计算重叠区域宽度

overlap_width = image2_transformed.shape[1] - width

if overlap_width <= 0:

return image2_transformed

# 创建线性渐变掩码

mask = np.ones((height, width + overlap_width, 3), dtype=np.float32)

for col in range(width, width + overlap_width):

alpha = (col - width) / overlap_width

mask[:, col, :] = 1 - alpha

# 应用掩码

image2_transformed[0:height, 0:width] = image1 * mask[0:height, 0:width] + \

image2_transformed[0:height, 0:width] * (1 - mask[0:height, 0:width])

return image2_transformed

def sift_image_stitching(image_path1, image_path2, output_path='./images/panorama_result.jpg'):

# 读取两张待拼接的图像

print(f'读取图像: {image_path1} 和 {image_path2}')

image1 = cv2.imread(image_path1)

image2 = cv2.imread(image_path2)

if image1 is None or image2 is None:

print('错误:无法读取图像,请检查文件路径')

return None

# 转换为RGB格式(因为OpenCV默认读取的是BGR格式)

image1_rgb = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)

image2_rgb = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB)

# 初始化SIFT检测器

print('初始化SIFT检测器...')

sift = cv2.SIFT_create()

# 检测SIFT特征点和计算描述符

print('检测SIFT特征点...')

kp1, des1 = sift.detectAndCompute(image1, None)

kp2, des2 = sift.detectAndCompute(image2, None)

# 使用FLANN匹配器匹配特征点

print('匹配特征点...')

FLANN_INDEX_KDTREE = 1

index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)

search_params = dict(checks=50)

flann = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(des1, des2, k=2)

# 筛选优质匹配点(根据Lowe的比率测试)

good_matches = []

for m, n in matches:

if m.distance < 0.7 * n.distance:

good_matches.append(m)

print(f'找到 {len(good_matches)} 个优质匹配点')

# 绘制匹配点并保存

matched_image = cv2.drawMatches(image1_rgb, kp1, image2_rgb, kp2, good_matches, None, flags=2)

matched_image_path = './images/sift_matching_result.png'

cv2.imwrite(matched_image_path, cv2.cvtColor(matched_image, cv2.COLOR_RGB2BGR))

print(f'匹配点图像已保存至: {matched_image_path}')

# 获取匹配点的坐标

points1 = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)

points2 = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

# 计算单应性矩阵(homography matrix)使用RANSAC算法

print('计算单应性矩阵...')

H, mask = cv2.findHomography(points2, points1, cv2.RANSAC, 5.0)

# 使用单应性矩阵变换图像2

height, width = image1.shape[:2]

# 计算输出图像的大小,确保能够容纳变换后的图像2和原图像1

stitched_width = width + image2.shape[1]

stitched_height = max(height, image2.shape[0])

print('变换图像...')

stitched_image = cv2.warpPerspective(image2, H, (stitched_width, stitched_height))

# 使用羽化过渡融合

print('应用羽化过渡融合...')

stitched_image = feather_blend(image1, stitched_image, width, height)

# 优化:裁剪黑边

print('裁剪黑边...')

# 寻找非黑色区域的边界

gray = cv2.cvtColor(stitched_image, cv2.COLOR_BGR2GRAY)

_, thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)

contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

x, y, w, h = cv2.boundingRect(contours[0])

stitched_image_cropped = stitched_image[y:y+h, x:x+w]

# 转换为RGB格式以便显示

stitched_image_rgb = cv2.cvtColor(stitched_image_cropped, cv2.COLOR_BGR2RGB)

# 保存拼接后的图像

cv2.imwrite(output_path, cv2.cvtColor(stitched_image_cropped, cv2.COLOR_RGB2BGR))

print(f'拼接图像已保存至: {output_path}')

# 显示结果

plt.figure(figsize=(18, 10))

plt.subplot(221)

plt.imshow(image1_rgb)

plt.title('图像1')

plt.axis('off')

plt.subplot(222)

plt.imshow(image2_rgb)

plt.title('图像2')

plt.axis('off')

plt.subplot(223)

plt.imshow(matched_image)

plt.title('特征点匹配')

plt.axis('off')

plt.subplot(224)

plt.imshow(stitched_image_rgb)

plt.title('拼接结果')

plt.axis('off')

plt.tight_layout()

plt.show()

return stitched_image_rgb

if __name__ == '__main__':

# 输入图像路径

image_path1 = './images/image_stitching_1.jpg'

image_path2 = './images/image_stitching_2.jpg'

# 执行图像拼接

print('开始图像拼接...')

result = sift_image_stitching(image_path1, image_path2)

if result is not None:

print('图像拼接完成!')

else:

print('图像拼接失败。')

🔍 小观察:运行代码时,注意观察控制台输出的信息。它会告诉你代码执行到了哪一步,找到了多少个优质匹配点,以及图像保存的路径。这些信息可以帮助你了解代码的执行状态,以及排查可能出现的问题。

相关数据

职享花怎么样?四个维度来认识它!
365万博首页

职享花怎么样?四个维度来认识它!

08-20 ↗ 4687
Photoshop制作水果糖
365万博首页

Photoshop制作水果糖

10-24 ↗ 7829
如何停止或转发邮件
bst365体育娱乐平台

如何停止或转发邮件

02-02 ↗ 8294
模拟农场25画面卡顿问题终极解决方法
bst365体育娱乐平台

模拟农场25画面卡顿问题终极解决方法

02-22 ↗ 5744