基於能量匹配的高斯金字塔與拉普拉斯金字塔圖像融合

利用拉普拉斯對高頻信息的保留,重建出原始圖像
操作過程如下
對於兩張圖像


可以看到兩張同樣的圖片一個臉部模糊一個除了臉其他地方模糊,現在我們需要通過局部能量匹配的融合方法對圖像進行增強,即基於能量特徵重建

通過一個簡單的二階差分可以看到兩幅圖邊緣差異,即一個臉部模糊一個除了臉其他地方模糊

所謂能量就是二階差分的邊緣像素強度,融合過程中對不同尺度上的兩幅圖提取能量最強的區域進行融合。
能量匹配過程如下步驟:

  1. 若該點匹配度M<e,則選擇該點能量大的圖,捨棄其餘。
  2. 若該點匹配度M>e,則根據能量大小分配權重,能量小的權重爲


能量大的權重爲

融合代碼爲

    E1 = imfilter(F11.^2, f, 'replicate');%計算能量
    E2 = imfilter(F12.^2, f, 'replicate');
    
    M = imfilter(F11.*F12, f, 'replicate').^2./(E1.*E2);%計算匹配度
    F11(E1<E2) = F12(E1<E2);%匹配度低時
    
    W_min = 0.5*(1 - (1-M)./(1-e));%計算權重
    W_max = 1 - W_min;
    F21 = W_min.*pyr1{i}+W_max.*pyr2{i};
    F22 = W_min.*pyr2{i}+W_max.*pyr1{i};
    F21(E1>E2) = F22(E1>E2);%匹配度高時
    
    F11(M>e) = F21(M>e);%按匹配度計算

試驗結果

下面給出完整matlab代碼


%局部能量特徵
clc
clear
close all

im1 = im2double(imread('lena1.jpg'));
im2 = im2double(imread('lena2.jpg'));
im1=im1(:,:,1);
im2=im2(:,:,1);
level = 4;%金字塔層數
sigma = 1;%金字塔每層提取的細節尺度。小了可能導致細節提取不充分,大了可能會導致融合結果失真。

im1_pyr = MLPD(im1, level, sigma);
im2_pyr = MLPD(im2, level, sigma);

pyr = pyr_fusion(im1_pyr, im2_pyr);

out = pyr{level};
for i = level-1 : -1 : 1
    out = pyr{i} + imresize(out,[size(pyr{i},1) size(pyr{i},2)],'bilinear');
end

imshow([im1 im2 out])
%------------------------------函數1 金字塔分解------------------------------
function pyr = MLPD(I, nlev, sigma)
%Laplacian Pyramid Decomposition
%多通道拉普拉斯金字塔分解
%   nlev  金字塔層數
%   sigma 高斯模糊程度

if ~exist('nlev', 'var')
    nlev = 4;
end

if ~exist('sigma', 'var')
    sigma = 1;
end

k = fspecial('gaussian', floor(sigma*3)*2+1, sigma);

%構建拉普拉斯金字塔
pyr = cell(nlev,1);
J = I;
for j = 1:nlev-1
    J_blur = imfilter(J, k, 'replicate');
    J_blur_down = J_blur(1:2:size(J_blur,1)-1,1:2:size(J_blur,2)-1, :); %downsample
    J_blur_high = imresize(J_blur_down,[size(J_blur,1) size(J_blur,2)],'bilinear');
    pyr{j} = J-J_blur_high;
    J=J_blur_down;
end
pyr{nlev}=J_blur_down; %最上一層即爲高斯金字塔
end
%------------------------------函數2 金字塔融合------------------------------
function pyr = pyr_fusion(pyr1,pyr2, e)
%pyramid fusion
%局部能量特徵的拉普拉斯金字塔融合

if ~exist('e', 'var')
    e = 0.6;
end

n = size(pyr1, 1);
pyr = cell(n, 1);

f = fspecial('average', [3 3]);

% 對每一層融合
for i=n:-1:1
    F11 = pyr1{i};
    F12 = pyr2{i};
    E1 = imfilter(F11.^2, f, 'replicate');%計算能量
    E2 = imfilter(F12.^2, f, 'replicate');
    %figure()
    %imshow(E1)
    
    M = imfilter(F11.*F12, f, 'replicate').^2./(E1.*E2);%計算匹配度
    
    F11(E1<E2) = F12(E1<E2);%匹配度低時
    
    W_min = 0.5*(1 - (1-M)./(1-e));%計算權重
    W_max = 1 - W_min;
    F21 = W_min.*pyr1{i}+W_max.*pyr2{i};
    F22 = W_min.*pyr2{i}+W_max.*pyr1{i};
    
    F21(E1>E2) = F22(E1>E2);%匹配度高時
    
    F11(M>e) = F21(M>e);%按匹配度計算
    figure()
    imshow((F11-min(F11))./(max(F11)-min(F11)))
    pyr{i} = F11;
end
end

下面爲完整python代碼

import cv2,numpy as np
import matplotlib.pyplot as plt
萊娜1=cv2.imread('lena1.jpg')
萊娜2=cv2.imread('lena2.jpg')
萊娜1=cv2.cvtColor(萊娜1,cv2.COLOR_BGR2RGB)
萊娜2=cv2.cvtColor(萊娜2,cv2.COLOR_BGR2RGB)
plt.subplot(121)
plt.imshow(萊娜1)
plt.subplot(122)
plt.imshow(萊娜2)

萊娜1=cv2.resize(萊娜1,(256,256),interpolation=cv2.INTER_CUBIC)
萊娜2=cv2.resize(萊娜2,(256,256),interpolation=cv2.INTER_CUBIC)
層數=8
temp=萊娜1.copy()
for index in range(層數):
    dst = cv2.pyrDown(temp)
def 創建拉普拉斯金字塔(path,level):
    img=cv2.imread(path)
    img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
    img= cv2.resize(img,(512,512),interpolation=cv2.INTER_CUBIC)
    temp = img.copy()#拷貝圖像
    高斯金字塔 = []
    高斯金字塔.append(img)
    for i in range(1,level):
        下采樣 = cv2.pyrDown(temp)
        高斯金字塔.append(下采樣)
        temp = 下采樣.copy()
    拉普拉斯金字塔 = [高斯金字塔[level-1]]
    for i in range(level-1,0,-1):
        上採樣 = cv2.pyrUp(高斯金字塔[i])
        第L層的高斯金字塔 = cv2.subtract(高斯金字塔[i-1],上採樣)
        拉普拉斯金字塔.append(第L層的高斯金字塔)
    print('高斯金字塔層數:',len(高斯金字塔),'拉普拉斯金字塔:',len(拉普拉斯金字塔))
    return 拉普拉斯金字塔
def 拉普拉斯卷積(原圖,卷積核大小):
    卷積核=np.ones([卷積核大小,卷積核大小])*1/(卷積核大小*卷積核大小)
    卷積圖 = np.zeros([原圖.shape[0]-(卷積核大小-卷積核大小//2),原圖.shape[1]-(卷積核大小-卷積核大小//2)])
    print(原圖.shape)
    原圖行數,原圖列數=原圖.shape
    for y in range(卷積核大小//2,原圖行數-(卷積核大小-卷積核大小//2)):
        for x in range(卷積核大小//2,原圖列數-(卷積核大小-卷積核大小//2)):
            半徑=卷積核大小//2
            拉普拉斯核 = np.array(([-1,-1,-1],[-1,8,-1],[-1,-1,-1]))
            窗口=np.sum(原圖[x-半徑:x+半徑+1,y-半徑:y+半徑+1]*拉普拉斯核)
            卷積圖[x, y] = 窗口
    return 卷積圖
萊娜1灰度=cv2.cvtColor(萊娜1,cv2.COLOR_RGB2GRAY)
萊娜1卷積圖=拉普拉斯卷積(萊娜1灰度,3)
萊娜2灰度=cv2.cvtColor(萊娜2,cv2.COLOR_RGB2GRAY)
萊娜2卷積圖=拉普拉斯卷積(萊娜2灰度,3)
plt.subplot(121)
plt.imshow(萊娜1卷積圖,'gray')
plt.subplot(122)
plt.imshow(萊娜2卷積圖,'gray')

def 平均值卷積(原圖,卷積核大小,通道):
    def 單通道卷積(原圖,卷積核大小):
        原圖=cv2.copyMakeBorder(原圖,卷積核大小//2,卷積核大小//2,卷積核大小//2,卷積核大小//2,cv2.BORDER_CONSTANT,0)
        卷積核=np.ones([卷積核大小,卷積核大小])*1/(卷積核大小*卷積核大小)
        卷積圖 = np.zeros([原圖.shape[0]-(卷積核大小-卷積核大小//2),原圖.shape[1]-(卷積核大小-卷積核大小//2)])
        原圖行數,原圖列數=原圖.shape
        for y in range(卷積核大小//2,原圖行數-(卷積核大小-卷積核大小//2)):
            for x in range(卷積核大小//2,原圖列數-(卷積核大小-卷積核大小//2)):
                半徑=卷積核大小//2
                窗口=原圖[x-半徑:x+半徑+1,y-半徑:y+半徑+1]
                卷積圖[x-1, y-1] = np.mean(窗口)
        return 卷積圖
    if 通道==3:
        for chanel in range(通道):
            原圖[:,:,chanel]=單通道卷積(原圖[:,:,chanel],卷積核大小)
        return 原圖
    return 單通道卷積(原圖,卷積核大小)
層數=3
萊娜=cv2.cvtColor(cv2.imread('lena.jpg'),cv2.COLOR_RGB2BGR)
拉普拉斯金字塔1=創建拉普拉斯金字塔('lena1.jpg',層數)
拉普拉斯金字塔2=創建拉普拉斯金字塔('lena2.jpg',層數)
萊娜灰度1=cv2.cvtColor(cv2.imread('lena1.jpg'),cv2.COLOR_BGR2GRAY)
萊娜灰度2=cv2.cvtColor(cv2.imread('lena2.jpg'),cv2.COLOR_BGR2GRAY)
萊娜1=cv2.cvtColor(cv2.imread('lena1.jpg'),cv2.COLOR_RGB2BGR)
萊娜2=cv2.cvtColor(cv2.imread('lena2.jpg'),cv2.COLOR_RGB2BGR)
萊娜灰度卷積=平均值卷積(萊娜灰度1,3,1)
print(萊娜灰度卷積.shape)
plt.figure('萊娜灰度卷積')
plt.imshow(萊娜灰度卷積,'gray')


能量復原算法

拉普拉斯金字塔4=[]
通道數=3
e=0.6
for i in range(0,層數):
    F=np.zeros(拉普拉斯金字塔1[i].shape)
    for chanel in range(通道數):
        F12=拉普拉斯金字塔1[i][:,:,chanel]
        F11=拉普拉斯金字塔2[i][:,:,chanel]

        E1 = 平均值卷積(F11,3,1)
        E2 = 平均值卷積(F12,3,1)
        M = np.power(平均值卷積(np.dot(F11,F12),3,1),2)/np.dot(E1,E2)
    
        F11[E1<E2] = F12[E1<E2] #匹配度低時
    
        W_min = 0.5*(1 - (1-M)/(1-e))
        W_max = 1 - W_min
        print(拉普拉斯金字塔1[i].shape,拉普拉斯金字塔2[i].shape)
#         兩圖分別乘以權值
        F21 = np.dot(W_min,拉普拉斯金字塔1[i][:,:,chanel])+np.dot(W_max,拉普拉斯金字塔2[i][:,:,chanel])
        F22 = np.dot(W_min,拉普拉斯金字塔2[i][:,:,chanel])+np.dot(W_max,拉普拉斯金字塔1[i][:,:,chanel])
        #匹配度高時
        F21[E1>E2] = F22[E1>E2]
        F11[M>e] = F21[M>e] #按匹配度計算
        
        print(F11.shape,F12.shape,E1.shape,E2.shape)
        F[:,:,chanel]=F11
    F=(F-np.min(F))/(np.max(F)-np.min(F))
    plt.figure()
    plt.imshow(F)
    拉普拉斯金字塔4.append(F)

#融合
ls_ = 拉普拉斯金字塔4[0]
for i in range(1,層數-1):
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_, 拉普拉斯金字塔4[i])

python結果

注:這裏我用的是jupyter,所以函數定義並沒那麼集中,以及爲了方便明確算法步驟,命名我故意使用的中文,至於爲什麼融合結果python和matlab有那麼大差異我也不太清楚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章