OpenCV計算機視覺實戰(12)——圖像金字塔與特征縮放
- 0. 前言
- 1. 高斯金字塔
- 1.1 應用場景
- 1.2 實現過程
- 2. 拉普拉斯金字塔
- 2.1 應用場景
- 2.2 實現過程
- 3. 圖像融合實例
- 3.1 應用場景
- 3.2 實現過程
- 小結
- 系列鏈接
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 gpgp1, 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 lplp1, 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)/255fused = (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)——邊緣檢測詳解