拉普拉斯金字塔融合原理浅析
前言
拉普拉斯金字塔融合(Laplacian Pyramid Blending)也稱為多頻帶融合(Multi-band Blending),可以看做是對Alpha融合的一種改進,避免出現鬼影(Ghosting)和截斷(Seams)現象。
方法原理
圖像可以認為是由不同頻率的信息組成,包含了很多不同的特征,頻譜跨度很大。
圖像中的低頻信號和高頻信號也叫做低頻分量和高頻分量。
圖像中的高頻分量,指的是圖像強度(亮度/灰度)變化劇烈的地方,也就是我們常說的邊緣(輪廓);
圖像中的低頻分量,指的是圖像強度(亮度/灰度)變換平緩的地方,也就是大片色塊的地方。
人眼對圖像中的高頻信號更為敏感。
因此對不同頻率分量選擇不同大小的融合窗口進行處理,在低頻處采用較大的融合窗口以避免截斷現象,在高頻處采用較小的融合窗口以避免鬼影現象,最終得到平滑無鬼影的融合結果。
具體算法流程如下:
1、對要融合的兩張圖片,構建拉普拉斯金字塔;
2、對于給定的融合區域,構建高斯金字塔;
3、對金字塔的每一層,應用類似Alpha融合的公式進行該層的融合;
4、利用融合后的金字塔重建出輸出圖像。
事實上,拉普拉斯金字塔的某層圖像就是源圖像減去丟掉高頻分量的圖像后的結果,也就是高頻分量,抽取出來用于后續高頻分量的融合以及恢復圖像高頻信息的恢復。關于高斯金字塔和拉普拉斯金字塔的釋義見參考資料[5]。
拉普拉斯金字塔示例:
拉普拉斯融合金字塔示例:
代碼實現
#!/usr/bin/python __author__ = 'TracelessLe'import numpy as np import cv2 import sys import argparsedef preprocess(img1, img2, overlap_w, flag_half, need_mask=False):if img1.shape[0] != img2.shape[0]:print ("error: image dimension error")sys.exit()if overlap_w > img1.shape[1] or overlap_w > img2.shape[1]:print ("error: overlapped area too large")sys.exit()w1 = img1.shape[1]w2 = img2.shape[1]if flag_half:shape = np.array(img1.shape)shape[1] = w1 // 2 + w2 // 2subA = np.zeros(shape)subA[:, :w1 // 2 + overlap_w // 2] = img1[:, :w1 // 2 + overlap_w // 2]subB = np.zeros(shape)subB[:, w1 // 2 - overlap_w // 2:] = img2[:,w2 - (w2 // 2 + overlap_w // 2):]if need_mask:mask = np.zeros(shape)mask[:, :w1 // 2] = 1return subA, subB, maskelse:shape = np.array(img1.shape)shape[1] = w1 + w2 - overlap_wsubA = np.zeros(shape)subA[:, :w1] = img1subB = np.zeros(shape)subB[:, w1 - overlap_w:] = img2if need_mask:mask = np.zeros(shape)mask[:, :w1 - overlap_w // 2] = 1return subA, subB, maskreturn subA, subB, Nonedef GaussianPyramid(img, leveln):GP = [img]for i in range(leveln - 1):GP.append(cv2.pyrDown(GP[i]))return GPdef LaplacianPyramid(img, leveln):LP = []for i in range(leveln - 1):next_img = cv2.pyrDown(img)LP.append(img - cv2.pyrUp(next_img, img.shape[1::-1]))img = next_imgLP.append(img)return LPdef blend_pyramid(LPA, LPB, MP):blended = []for i, M in enumerate(MP):blended.append(LPA[i] * M + LPB[i] * (1.0 - M))return blendeddef reconstruct(LS):img = LS[-1]for lev_img in LS[-2::-1]:img = cv2.pyrUp(img, lev_img.shape[1::-1])img += lev_imgreturn imgdef multi_band_blending(img1, img2, mask, overlap_w, leveln=None, flag_half=False, need_mask=False):if overlap_w < 0:print ("error: overlap_w should be a positive integer")sys.exit()if need_mask: # no input masksubA, subB, mask = preprocess(img1, img2, overlap_w, flag_half, True)else: # have input masksubA, subB, _ = preprocess(img1, img2, overlap_w, flag_half)max_leveln = int(np.floor(np.log2(min(img1.shape[0], img1.shape[1],img2.shape[0], img2.shape[1]))))if leveln is None:leveln = max_levelnif leveln < 1 or leveln > max_leveln:print ("warning: inappropriate number of leveln")leveln = max_leveln# Get Gaussian pyramid and Laplacian pyramidMP = GaussianPyramid(mask, leveln)LPA = LaplacianPyramid(subA, leveln)LPB = LaplacianPyramid(subB, leveln)# Blend two Laplacian pyramidspassblended = blend_pyramid(LPA, LPB, MP)# Reconstruction processresult = reconstruct(blended)result[result > 255] = 255result[result < 0] = 0return result.astype(np.uint8)if __name__ == '__main__':# construct the argument parse and parse the argumentsap = argparse.ArgumentParser(description="A Python implementation of multi-band blending")ap.add_argument('-f', '--first', required=True,help="path to the first (left) image")ap.add_argument('-s', '--second', required=True,help="path to the second (right) image")ap.add_argument('-m', '--mask', required=False,help="path to the mask image")ap.add_argument('-o', '--overlap', required=True, type=int,help="width of the overlapped area between two images, \even number recommended")ap.add_argument('-l', '--leveln', required=False, type=int,help="number of levels of multi-band blending, \calculated from image size if not provided")ap.add_argument('-H', '--half', required=False, action='store_true',help="option to blend the left half of the first image \and the right half of the second image")args = vars(ap.parse_args())flag_half = args['half']img1 = cv2.imread(args['first'])img2 = cv2.imread(args['second'])if args['mask'] != None:mask = cv2.imread(args['mask'])mask = mask//255need_mask = Falseelse:mask = Noneneed_mask =Trueoverlap_w = args['overlap']leveln = args['leveln']print('args: ', args)result = multi_band_blending(img1, img2, mask, overlap_w, leveln, flag_half, need_mask)cv2.imwrite('result.png', result)print("blending result has been saved in 'result.png'")輸入:
輸出:
其他
關于更多圖像融合方法可以查閱參考資料中關于泊松融合的內容。
版權說明
本文為原創文章,獨家發布在blog.csdn.net/TracelessLe。未經個人允許不得轉載。如需幫助請email至tracelessle@163.com。
參考資料
[1] Image Blending Using Laplacian Pyramids | by Michelle Zhao | Becoming Human: Artificial Intelligence Magazine
[2] 圖像高頻和低頻_Code_LiShi的博客-CSDN博客_圖片高頻和低頻
[3] 圖像合成與圖像融合 - 知乎
[4] 圖像融合之拉普拉斯融合_qingyun_wudaoletu的博客-CSDN博客_拉普拉斯融合
[5] 空域分析及變換(2):高斯拉普拉斯金字塔_fb_941219的博客-CSDN博客
[6] Panoramic Image Mosaic
[7] multi-band-blending-python/multi_band_blending.py at master · TracelessLe/multi-band-blending-python
[8] 泊松融合原理淺析_TracelessLe的專欄-CSDN博客
[9] Blending and Compositing.pdf-圖像處理文檔類資源-CSDN文庫
[10] Project: Poisson Image Editing
[11] Gradient Domain Fusion Using Poisson Blending
[12] Gradient Domain Blending
[13] OpenCV: Image Pyramids
[14] OpenCV: Image Filtering - pyrUp()
[15] OpenCV: Image Filtering - pyrDown()
[16] OpenCV: Image Pyramids
[17] cv::Laplacian - opencv/deriv.cpp at 68d15fc62edad980f1ffa15ee478438335f39cc3 · opencv/opencv
總結
以上是生活随笔為你收集整理的拉普拉斯金字塔融合原理浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebView纯浏览模式,webView
- 下一篇: Quick Cocos2dx 场景转换问