1. 程式人生 > >運動模糊恢復

運動模糊恢復

維納濾波—deconvwnr函式利用維納濾波器來對影象模糊修復

function image_restoration_deconvwnr()
    %Read image
    I = im2double(imread('lena.tif'));
    I=rgb2gray(I);
    figure,subplot(2,3,1),imshow(I);
    title('Original Image');

    %Simulate a motion blur
    LEN = 21;
    THETA = 11;
    PSF = fspecial('motion', LEN, THETA);  %獲得濾波運算元 PSF
    blurred = imfilter(I, PSF, 'conv', 'circular');
    subplot(2,3,2),imshow(blurred);
    title('Blurred Image');

    %Restore the blurred image
    wnr1 = deconvwnr(blurred, PSF, 0);
    subplot(2,3,3),imshow(wnr1);
    title('Restored Image');

    %Simulate blur and noise
    noise_mean = 0;
    noise_var = 0.0001;
    blurred_noisy = imnoise(blurred, 'gaussian', ...
                            noise_mean, noise_var);
    subplot(2,3,4),imshow(blurred_noisy)
    title('Simulate Blur and Noise')

    %Restore the blurred and noisy image:First attempt
    wnr2 = deconvwnr(blurred_noisy, PSF, 0);
    subplot(2,3,5);imshow(wnr2);title('Restoration of Blurred, Noisy Image Using NSR = 0')

    %Restore the Blurred and Noisy Image: Second Attempt
    signal_var = var(I(:));
    wnr3 = deconvwnr(blurred_noisy, PSF, noise_var / signal_var);
    subplot(2,3,6),imshow(wnr3)
    title('Restoration of Blurred, Noisy Image Using Estimated NSR');
end


維納濾波需要估計影象的信噪比(SNR)或者噪信比(NSR),訊號的功率譜使用影象的方差近似估計,噪聲分佈是已知的。從第一排中可以看出,若無噪聲,此時維納濾波相當於逆濾波,恢復運動模糊效果是極好的。從第二排可以看出噪信比估計的準確性對影象影響比較大的,二排中間效果幾乎不可用。

逆濾波

function image_restoration_matlab()
    % Display the original image.
    I = im2double(imread('lena.tif'));
    I=rgb2gray(I);
    [hei,wid,~] = size(I);
    subplot(2,3,1),imshow(I);
    title('Original Image (courtesy of MIT)');


    % Simulate a motion blur.
    LEN = 21;
    THETA = 11;
    PSF = fspecial('motion', LEN, THETA);
    blurred = imfilter(I, PSF, 'conv', 'circular');
    subplot(2,3,2), imshow(blurred); title('Blurred Image');

    % Inverse filter
    If = fft2(blurred);
    Pf = fft2(PSF,hei,wid);
    deblurred = ifft2(If./Pf);
    subplot(2,3,3), imshow(deblurred); title('Restore Image')

    % Simulate additive noise.
    noise_mean = 0;
    noise_var = 0.0001;
    blurred_noisy = imnoise(blurred, 'gaussian', ...
                            noise_mean, noise_var);
    subplot(2,3,4), imshow(blurred_noisy)
    title('Simulate Blur and Noise')

    % Try restoration assuming no noise.
    If = fft2(blurred_noisy);
    deblurred2 = ifft2(If./Pf);
    subplot(2,3,5), imshow(deblurred2)
    title('Restoration of Blurred Assuming No Noise');

    % Try restoration with noise is known.
    noisy = blurred_noisy - blurred;
    Nf = fft2(noisy);
    deblurred2 = ifft2(If./Pf - Nf./Pf);
    subplot(2,3,6), imshow(deblurred2)
    title('Restoration of Blurred with Noise Is Known')
end


逆濾波對噪聲非常敏感,除非我們知道噪聲的分佈情況(事實上,這也很難知道),逆濾波幾乎不可用,可以從二排中間看出,恢復影象效果極差。但若知道噪聲分佈,也是可以完全復原資訊的。可以從二排最後一張圖可以看出。

注:影象恢復時需要用到 PSF 卷積核,該卷積核為生成運動模糊得卷積核,在實際應用場景是不知道的。
 

如何求解: PSF

PSF 是由 LEN 和 Theta 決定的,如果能求出 運動模糊的方向,和對應的偏移量就能求出 PSF

 

1、基本原理:

      點擴散函式PSF主要有兩個重要引數:(1)模糊方向;(2)模糊尺度。本次主要是針對第一個引數----模糊方向的估計進行了研究。運動模糊方向是指運動方向與水平方向的夾角,由文獻得知運動模糊主要是降低了運動方向的高頻成分,而對其他方向的高頻成分影響較小。常見的辨識方法有頻域法和倒譜法,wym 兩種方法都試過,模擬實驗結果表兩種方法各有好處。

      頻域法的原理是將退化影象進行二維傅立葉變換,得到具有相互平行的規則明暗條紋的頻譜。設暗紋與 x 軸正向夾角為 φ ,運動模糊方向與 x 軸夾角為 θ ,影象尺寸為 M × N,根據傅立葉變換的時頻特性可以知道,可通過公式 tan(θ) = tan(φ − 90°) × M/N  得到模糊角度 θ ,因此只要通過 Radon 變換檢測出頻譜暗條紋與水平方向的夾角即可到運動模糊方向。

      倒譜法的主要原理是先將退化影象進行二維傅立葉變換,然後取對數,再進行反傅立葉變換得到退化影象的倒頻譜,分離出退化影象的模糊資訊,進而通過 Radon 變換得到運動模糊方向。

      Radon 變換是對頻譜圖上某一指定角度進行線積分,通過計算1°~180°的Radon變換得到180列的矩陣 R,每一列向量是影象在一個角度上沿一族直線的積分投影,因為積分直線束與頻譜中的亮暗條紋平行,所以所得的投影向量中應有一個最大值,在頻域法中最大值所對應的列數就等於模糊方向與x軸正方向水平夾角;在倒譜法中,最大值對應的列數 ±90°即為所求的模糊角度。

      具體理論和公式推導就不列出來了。。有興趣的同學請 STFW。。(什麼?不知道什麼是 STFW? 請自行 STFW。。)

2、演算法實現:

  (1)頻域法

    1)     對模糊影象進行灰度化,並計算其二維傅立葉變換;

    2)     對傅立葉變換值的動態範圍進行壓縮;

    3)     對壓縮後的結果進行迴圈移位,使其低頻成分居中;

    4)     用canny運算元對壓縮居中後的頻譜影象進行邊緣檢測使其二值化;

    5)     將二值化後的頻譜圖做從1°~180°的radon變換;

    6)     找出radon變換後的矩陣中的最大值,求出其對應的列數 n;

    7)     通過公式 tan(θ) = tan(φ − 90°) × M/N  = tan(n − 90°) × M/N 求出運動模糊方向。

    實現程式碼:

close all;
clear all;

%% 讀入並顯示影象
filename = 'ex.jpg';
I = imread(filename);

figure
imshow(uint8(I));
title('原圖');

%% 生成運動模糊影象
PSF = fspecial('motion',50, 120);
g = imfilter(I, PSF, 'circular');
figure 
imshow(uint8(g));
title('運動模糊圖');

%% 對運動模糊影象進行灰度化,並進行二維快速傅立葉變換,生成其頻譜圖
gb = rgb2gray(g);
figure
imshow(uint8(gb));
PQ = paddedsize(size(gb));
F = fft2(gb, PQ(1), PQ(2));
figure
imshow(uint8(F));


%% 將頻譜壓縮,居中
H = log(1+abs(F));
Hc = fftshift(H);
figure
imshow(uint8(Hc));

%% 用canny運算元將壓縮居中後的頻譜圖進行邊緣檢測,二值化
T = graythresh(Hc);
bw=edge(Hc, 'canny', T);
figure
imshow(bw);

%% 對二值化後的頻譜圖進行radon變換
theta = 1:180;
R = radon(bw, theta);
figure
imshow(R);

%% 計算出通過radon變換求出的模糊角度
MAX = max(max(R));
[m, n] = find(R == MAX);
[M,N] = size(Hc);
beita = atan(tan(n*pi/180)*M/N)*180/pi;

(2)倒譜法:

        

       1)     對模糊影象進行灰度化,並計算其二維傅立葉變換;

       2)     對傅立葉變換取對數,平方後再進行一次反傅立葉變換得到其倒頻譜;

       3)     對倒頻譜動態範圍進行壓縮;

       4)     對壓縮後的結果進行迴圈移位,使其低頻成分居中;

       5)     用canny運算元對壓縮居中後的頻譜影象進行邊緣檢測使其二值化;

       6)     將二值化後的頻譜圖做從1°~180°的radon變換;

       7)     找出radon變換後的矩陣中的最大值,其對應的列數±90°即為所求的模糊方向。

       實現程式碼:

close all;
clear all;

%% 讀入並顯示影象
filename = 'ex.jpg';
I = imread(filename);

figure
imshow(uint8(I));
title('原圖');

%% 生成運動模糊影象
PSF = fspecial('motion',80, 150);
g = imfilter(I, PSF, 'circular');
figure 
imshow(uint8(g));
title('運動模糊圖');

%% 對運動模糊影象進行灰度化,並進行二維快速傅立葉變換,生成其頻譜圖
gb = rgb2gray(g);
figure
imshow(uint8(gb));
PQ = paddedsize(size(gb));
F = fft2(gb, PQ(1), PQ(2));
figure
imshow(uint8(F));

%% 作出倒頻譜
F1 = log(1+abs(F));
F2 = abs(F1).^2;
F3 = real(ifft2(F2));
figure
imshow(uint8(F3));


%% 將倒頻譜壓縮,居中
H = log(1+abs(F3)); % 將倒頻譜動態範圍進行壓縮
Hc = fftshift(H); % 將壓縮結果進行迴圈移位,使低頻成分居中
figure
imshow(uint8(Hc));

%% 通過閾值處理,邊緣檢測“canny”運算元二值化倒頻譜
T = graythresh(Hc);
bw=edge(Hc, 'canny', T);
figure
imshow(bw);

%% 對倒頻譜從1°到180°作radon變換,以求出模糊角度
theta = 1:180;
R = radon(bw, theta);
figure
imshow(R);

%% 計算出通過倒頻譜radon變換估計出的模糊角度
MAX = max(max(R));
[m, n] = find(R == MAX);
if 90 < n <= 180
   beita = n - 90;
else if 0 < n < 90
        beita = n + 90;
    else if n == [90;90] | n == [180;180]
            beita = n(1);
        end;

7、模擬結果及演算法評價:

     經過反覆、多次、令人崩潰的除錯引數,得出結論,模糊角度估計的精確度主要與邊緣檢測的閾值 T,運動模糊尺度和運動模糊方向這三個變數有關,經除錯,閾值選取由graythresh 函式算出的全域性閾值效果較好,而模糊尺度越小精度越低。

      頻域法:當模糊尺度大於20畫素時,模糊方向處於0°~90°時,檢測效果很好,誤差低於0.5°,但當模糊尺度低於20畫素時,由於中心化處理致使頻譜圖中間出現的十字亮線使模糊方向常為90°或180°;而當模糊尺度大於90°時,估計到的模糊方向像脫繮的野馬。。完全不知道怎麼才能估計出如此噁心的資料的。。

     倒譜法:當模糊尺度大於40畫素時,可以檢測的模糊方向較大,基本從0°到180°都可以檢測,不過誤差在5°左右,模糊尺度小於40畫素時誤差就很大了,不能用作檢測

 

關於偏移距離的計算 可以使用 折中法試探,每次試探一半的距離,然後根據恢復結果的影象質量進一步選取新的距離值。 關於影象質量評價可以使用紋理特徵,例如 Sobel 濾波後的均值,或者 拉普拉斯運算元 濾波的方差,或者取傅立葉變換後的高頻資訊均值。