前言
图片拼接在许多领域都有广泛的应用,包括但不限于以下几个方面:
-
全景摄影:在摄影中,通过将多张照片拼接在一起可以实现全景照片的效果。这在旅游景点、房地产展示等领域有着广泛的应用,能够提供更加生动、真实的视觉体验。
-
医学影像处理:在医学影像领域,例如 CT、MRI 等影像数据的拼接可以帮助医生获取更加完整的患者信息,进而进行更精确的诊断和治疗计划制定。
-
地图制作:地图制作中常常需要将多个局部地图或航拍影像拼接成较大范围的地图,以满足城市规划、导航、军事应用等领域的需求。
-
无人机航拍:在无人机航拍领域,通过将无人机航拍获取的多张照片进行拼接,可以生成更加细致和全面的航拍影像,用于农业、环境监测、工程测绘等领域。
-
虚拟现实(VR)和增强现实(AR):在虚拟现实和增强现实技术中,图片拼接可以用来创建虚拟环境或增强真实环境,提供更加沉浸式的体验。
-
文物修复和数字化:在文物保护领域,通过对文物的多角度拍摄并进行拼接,可以实现对文物的三维重建和数字化保存,以及对文物进行修复和研究。
代码
重叠拼接
将相同位置的图片进行叠加
import cv2
import numpy as np
# 加载图片
image1 = cv2.imread('D:\\sucai\\image1.png')
image2 = cv2.imread('D:\\sucai\\image2.png')
save_img = 'D:\\sucai\\merge_image_simple.png'
# 确定目标图像大小
height = max(image1.shape[0], image2.shape[0])
width = max(image1.shape[1], image2.shape[1])
target_image = np.zeros((height, width, 3), dtype=np.uint8)
# 叠加图片
target_image[:image1.shape[0], :image1.shape[1]] = image1
target_image[:image2.shape[0], :image2.shape[1]] += image2 # 叠加在同一位置
# 显示结果
cv2.imshow('Simple Blend', target_image)
cv2.imwrite(save_img, target_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
重叠拼接(加权)
在OpenCV中,cv2.addWeighted()
函数可以用来对两幅图像进行加权相加,产生一幅新的图像
通过调整alpha
和beta
的值,可以控制不同图像在最终混合结果中所占比重,从而实现不同的混合效果。
import cv2
# 读取两幅图像
img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
image_obj_list = [cv2.imread(i) for i in img_path_list]
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 设置权重参数
"""
src1:第一幅输入图像。
alpha:第一幅图像的权重。
src2:第二幅输入图像。
beta:第二幅图像的权重。
gamma:一个可选的参数,用于控制加权和的常数值。
"""
alpha = 0.5
beta = 0.5
gamma = 0
# 对两幅图像进行加权相加
merged_image = cv2.addWeighted(image_obj_list[0], alpha, image_obj_list[1], beta, gamma)
# 显示结果
cv2.imshow('Blended Image', merged_image)
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
水平拼接
import cv2
img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
save_img = 'D:\\sucai\\merge_image.png'
image_obj_list = [cv2.imread(i) for i in img_path_list]
# 获取所有图片的尺寸大小
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
# 统一子图的尺寸大小
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 水平拼接
merged_image = cv2.hconcat(image_obj_list)
# 显示合并后的图片
cv2.imshow('Merged Image', merged_image)
# 保存图片
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
垂直拼接
import cv2
img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
save_img = 'D:\\sucai\\merge_image.png'
image_obj_list = [cv2.imread(i) for i in img_path_list]
# 获取所有图片的尺寸大小
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
# 统一子图的尺寸大小
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 垂直拼接
merged_image = cv2.vconcat(image_obj_list)
# 显示合并后的图片
cv2.imshow('Merged Image', merged_image)
# 保存图片
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
全景拼接
拼接器使用这些重叠区域中的特征点来找到图像间的对应关系。如果重叠区域过小或者不存在,拼接器可能无法找到足够的匹配特征点进行拼接。
import sys
import cv2
img1 = cv2.imread('D:\\sucai\\2\\image1.png')
img2 = cv2.imread('D:\\sucai\\2\\image2.png')
save_img = 'D:\\sucai\\merge_image.png'
# 检查图像是否正确加载
if img1 is None or img2 is None:
print("其中一个或两个图像加载失败")
sys.exit()
img_obj = cv2.Stitcher.create(cv2.Stitcher_PANORAMA)
(status, stitched_image) = img_obj.stitch((img1, img2))
if status != cv2.Stitcher_OK:
print("不能拼接图片, error code = %d" % status)
else:
print("拼接成功.")
cv2.imshow('pano', stitched_image)
cv2.imwrite(save_img, stitched_image)
cv2.waitKey()
cv2.destroyAllWindows()
sys.exit()
前景图和背景图拼接
注意:前景图需要作个缩放处理,小于背景图.
save_img = 'D:\\sucai\\merge_image.png'
img_list = ['D:\\sucai\\5\\foreground.png', 'D:\\sucai\\5\\background.png']
img_fg = cv2.imread(img_list[0]) # 读取前景图
img_bg = cv2.imread(img_list[1]) # 读取背景图
# 读取背景图和前景图的像素和通道数
rows_bg, cols_bg, channels_bg = img_bg.shape
rows_fg, cols_fg, channels_fg = img_fg.shape
# 为了防止批处理时有可能出现前景图像素尺寸大于背景图的情况,做一个缩小前景图的操作
rows_change_fg = rows_fg // 6
cols_change_fg = cols_fg // 6
# 把前景图缩小
img_fg = cv2.resize(img_fg, (cols_change_fg, rows_change_fg), interpolation=cv2.INTER_LINEAR)
# 选择背景图中对应大小的区域
start_row = 240
start_col = 280
roi = img_bg[start_row:rows_change_fg+start_row, start_col:cols_change_fg+start_col]
# 将前景图转换为灰度图
img_fg2gray = cv2.cvtColor(img_fg, cv2.COLOR_BGR2GRAY)
# 创建掩膜
ret, mask = cv2.threshold(img_fg2gray, 255, 255, cv2.THRESH_BINARY)
# 掩膜取反
mask_inv = cv2.bitwise_not(mask)
# 使用掩膜进行图像合并
img_bg_bg = cv2.bitwise_and(roi, roi, mask=mask)
img_fg_fg = cv2.bitwise_and(img_fg, img_fg, mask=mask_inv)
dst = cv2.add(img_bg_bg, img_fg_fg)
img_bg[start_row:rows_change_fg + start_row, start_col:cols_change_fg+start_col] = dst
cv2.imshow('merge_image', img_bg)
cv2.imwrite(save_img, img_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()