OpenCV计算机视觉实战(12)——图像金字塔与特征缩放
0. 前言
图像金字塔技术通过对原始图像按不同分辨率进行多层次表示,不仅能提升计算效率,还能为图像融合、检测与识别提供多尺度特征。高斯金字塔 (Gaussian Pyramid
) 用于构建多级低通图像,拉普拉斯金字塔 (Laplacian Pyramid
) 则提取各层之间的细节信息。本节将深入介绍如何使用 OpenCV
构建高斯与拉普拉斯金字塔,并以经典的图像融合案例,展示图像金字塔在特征缩放与融合中的强大应用。
1. 高斯金字塔
高斯金字塔通过不断下采样与高斯平滑,将图像分解为一系列分辨率逐渐降低的图像,用于多尺度分析与加速算法。
1.1 应用场景
- 多尺度目标检测:在目标尺寸未知或变化剧烈的场景(如行人检测、车牌识别)下,高斯金字塔可帮助算法在不同分辨率图像上快速定位目标
- 加速模板匹配:先在低分辨率层做初步匹配,再在高分辨率层精细搜索,大幅减少计算量
- 图像预览:在线地图或大尺寸全景图浏览,用金字塔在不同缩放级别下平滑加载
1.2 实现过程
- 初次平滑:避免混叠
- 由于下采样会丢弃高频信息,先用
cv2.GaussianBlur
做一次适度平滑 - 核大小
ksize = 2·⌈3*alpha⌉ + 1
,一般alpha
取1.0~1.5
- 由于下采样会丢弃高频信息,先用
- 连续下采样
cv2.pyrDown
会自动结合5 × 5
高斯滤波与采样,对比手动GaussianBlur + resize
更高效且抗混叠- 每层分辨率缩小为前一层的 1 2 \frac 12 21,层数视应用而定
- 可视化
- 将各层图像拼接或依次显示,便于对比分辨率变化
import cv2
import numpy as np
# 1. 读取并预平滑
img = cv2.imread('1.jpeg')
alpha = 1.2
ksize = int(2 * np.ceil(3*alpha) + 1)
blur = cv2.GaussianBlur(img, (ksize, ksize), alpha)
# 2. 构建高斯金字塔(5 层)
gp = [blur]
for i in range(1, 5):
gp.append(cv2.pyrDown(gp[i-1]))
# 3. 显示各层
for idx, layer in enumerate(gp):
cv2.imshow(f'Gaussian Level {idx}', layer)
cv2.waitKey(0)
cv2.destroyAllWindows()
关键函数解析:
cv2.pyrDown(src)
:对输入图像做高斯滤波后,下采样至宽高各自减半cv2.GaussianBlur(src, ksize, sigma)
:在下采样前做平滑,减少高频信息引发的混叠效应
2. 拉普拉斯金字塔
拉普拉斯金字塔通过相邻两层高斯金字塔的差分,提取出各尺度的细节信息,可用于图像重建与增强。
2.1 应用场景
- 图像压缩:只存储拉普拉斯层与顶层高斯图,就能高效重建原图
- 特效增强:对细节层做强化或减弱,可实现“锐化”“虚化”特效
- 多分辨率融合:在图像融合中,用拉普拉斯金字塔融合能避免明显拼接痕迹
2.2 实现过程
- 构建高斯金字塔
- 使用上一节生成的高斯金字塔列表
gp
- 使用上一节生成的高斯金字塔列表
- 计算拉普拉斯层
- 对于第 i i i 层高斯图像,将其上采样 (
pyrUp
),使其尺寸与第 i − 1 i-1 i−1 层对齐 - 将第 i − 1 i-1 i−1 层高斯图像减去上采样结果,得到第 i − 1 i-1 i−1 层的拉普拉斯图像
- 最后一层直接作为拉普拉斯金字塔的顶层
- 对于第 i i i 层高斯图像,将其上采样 (
- 重建验证
- 从顶层开始,依次上采样并与对应拉普拉斯层相加,验证重建结果与原图接近
import cv2
import numpy as np
# 1. 读取并预平滑
img = cv2.imread('1.jpeg')
alpha = 1.2
ksize = int(2 * np.ceil(3*alpha) + 1)
blur = cv2.GaussianBlur(img, (ksize, ksize), alpha)
# 2. 构建高斯金字塔(5 层)
gp = [blur]
for i in range(1, 5):
gp.append(cv2.pyrDown(gp[i-1]))
# 3. 构建拉普拉斯金字塔
lp = []
for i in range(4):
up = cv2.pyrUp(gp[i+1], dstsize=(gp[i].shape[1], gp[i].shape[0]))
lap = cv2.subtract(gp[i], up)
lp.append(lap)
lp.append(gp[-1]) # 顶层
# 4. 重建图像
recon = lp[-1]
for i in range(3, -1, -1):
recon = cv2.pyrUp(recon, dstsize=(lp[i].shape[1], lp[i].shape[0]))
recon = cv2.add(recon, lp[i])
cv2.imshow('Reconstructed', recon)
cv2.waitKey(0)
cv2.destroyAllWindows()
关键函数解析:
cv2.pyrUp(src, dstsize)
:将图像上采样至目标尺寸,并做插值平滑cv2.subtract(src1, src2)
:逐像素相减,提取细节层cv2.add(src1, src2)
:逐像素相加,用于图像重建
3. 图像融合实例
接下来,利用拉普拉斯金字塔将两幅图像在多尺度上分解,逐层融合细节,再重建,实现平滑且无明显接缝的混合效果。
3.1 应用场景
- 无缝拼接:将两张风格迥异的图像在中间或曲线边界处平滑融合(如半脸融合、天空拼接)
- 曝光融合:不同曝光度的同一场景,用多尺度融合获得
HDR
效果 - 拼贴艺术:在广告、海报设计中,通过金字塔融合创造奇幻视觉效果
3.2 实现过程
- 图像准备与对齐
- 确保两幅图尺寸一致
- 若需要变形对齐,可先用特征匹配 + 单应性 (
Homography
) 校正
- 构建金字塔
- 高斯:
gp1
,gp2
- 拉普拉斯:
lp1
,lp2
- 高斯:
- 层级融合策略
- 硬切:每层直接水平或竖直拼接
- 渐变掩码:对每层生成一个软掩码(如高斯模糊的二值斑块),按权重混合
L = M·L1 + (1−M)·L2
- 多掩码:根据图像内容动态选取掩码,如人脸融合时在面部区域采用圆形渐变
- 金字塔重建
- 从顶层小图开始,逐层上采样、与融合后的拉普拉斯层相加
- 重建后可做全局色调/对比度微调,让拼接边界更自然
import cv2
import numpy as np
# 1. 读取与对齐
img1 = cv2.imread('1.jpeg')
img2 = cv2.imread('2.jpeg')
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
# 2. 构建高斯金字塔
def build_gp(img, levels=6):
gp = [img]
for _ in range(levels):
gp.append(cv2.pyrDown(gp[-1]))
return gp
gp1, gp2 = build_gp(img1), build_gp(img2)
# 3. 构建拉普拉斯金字塔
def build_lp(gp):
lp = []
for i in range(len(gp)-1):
up = cv2.pyrUp(gp[i+1], dstsize=(gp[i].shape[1], gp[i].shape[0]))
lp.append(cv2.subtract(gp[i], up))
lp.append(gp[-1])
return lp
lp1, lp2 = build_lp(gp1), build_lp(gp2)
# 4. 生成渐变掩码金字塔
mask = np.zeros_like(img1, dtype=np.float32)
# 中心向左右平滑过渡
cols = img1.shape[1]
mask[:, :cols//2] = 1.0
mask = cv2.GaussianBlur(mask, (51,51), 0)
gp_mask = build_gp((mask*255).astype(np.uint8), levels=6)
# 5. 融合拉普拉斯层
lp_fused = []
for l1, l2, gm in zip(lp1, lp2, gp_mask):
gm_f = gm.astype(np.float32)/255
fused = (l1.astype(np.float32)*gm_f + l2.astype(np.float32)*(1-gm_f))
lp_fused.append(fused.astype(np.uint8))
# 6. 重建融合图
fused = lp_fused[-1]
for i in range(len(lp_fused)-2, -1, -1):
fused = cv2.pyrUp(fused, dstsize=(lp_fused[i].shape[1], lp_fused[i].shape[0]))
fused = cv2.add(fused, lp_fused[i])
# 7. 全局微调
fused = cv2.detailEnhance(fused, sigma_s=10, sigma_r=0.15)
cv2.imshow('Pyramid Blended', fused)
cv2.waitKey(0)
cv2.destroyAllWindows()
关键函数解析:
- 渐变掩码:用
cv2.GaussianBlur
将硬掩码平滑,实现层级软混合 build_gp
/build_lp
:封装高斯与拉普拉斯金字塔构建流程,便于复用cv2.detailEnhance(src, sigma_s, sigma_r)
:调节融合后细节与对比度,OpenCV
的画龙点睛- 多级融合策略:硬切、软掩码、基于内容的掩码,用于不同艺术或工程需求
小结
在本节中,我们介绍了如何在 OpenCV
中构建图像金字塔、提取多尺度特征,并应用于无缝图像融合。掌握这些技术,能够为图像处理、计算机视觉和深度学习任务提供强有力的多尺度支持。
系列链接
OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(8)——图像滤波详解
OpenCV计算机视觉实战(9)——阈值化技术详解
OpenCV计算机视觉实战(10)——形态学操作详解
OpenCV计算机视觉实战(11)——边缘检测详解