注:本系列來自於圖像處理課程實驗,用Matlab實現最基本的圖像處理算法
1.Fourier變換
(1)頻域增強
除了在空間域內可以加工處理圖像以外,我們還可以將圖像變換到其他空間後進行處理,這些方法稱爲變換域方法,最常見的變換域是頻域。
使用Fourier變換把圖像從空間域變換到頻域,在頻域內做相應增強處理,再從頻域變換到空間域得到處理後的圖像。
我們這裏主要學習Fourier變換和FFT變換的算法,沒有學過通信原理,我對信號、時域分析也不是很清楚。
2.FFT算法
(1)離散Fourier變換,DFT
函數
很顯然求出所有的長度爲N的信號的DFT需要
(2)快速Fourier變換,FFT
快速傅立葉變換FFT是利用單位複數根的特殊性質(消去引理和折半引理,見《算法導論》(第3版中文版)P532詳細論述),在
FFT有兩種基本實現方式:
- 遞歸FFT
- 迭代FFT,也叫FFT蝶式運算
遞歸FFT由於遞歸棧開銷大且容量有限等缺陷(但理解容易),一般計算採取迭代FFT實現。
(3)迭代FFT
直接給出算法導論版本的迭代FFT算法:
其中求逆序數拷貝的函數爲:
FFT採用折半迭代的思想,因此速度能降低到
(4)迭代FFTMatlab實現
Matlab有fft函數,我們也可以自己實現:
function [ fft_m ] = IterativeFFT( vec )
clear i;
n = length(vec);
fft_m = BitReverseCopy(vec);
for s = 1 : log2(n)
m = power(2, s);
wm = exp(- 2 * pi * i / m);
for k = 0 : m : n - 1
w = 1;
for j = 0 : m / 2 - 1
t = w * fft_m(k + j + m / 2 + 1);
u = fft_m(k + j + 1);
fft_m(k + j + 1) = u + t;
fft_m(k + j + m / 2 + 1) = u - t;
w = w * wm;
end
end
end
end
BitReverseCopy函數如下:
function [ copy ] = BitReverseCopy( vec )
n = length(vec);
copy = zeros(1, n);
bitn = log2(n);
for i = 0 : n - 1
revi = bin2dec(fliplr(dec2bin(i, bitn)));
copy(revi + 1) = vec(i + 1);
end
end
需要特別注意的是:
- 一般給出的FFT算法僞代碼都是基於下標從零開始的數組,寫在Matlab需要考慮映射關係
clear i
是爲了怕之前有變量i和複數記號i混淆,清楚Matlab workspace中的緩存- 默認vec是double類型的!因爲中間採用許多double類型運算
3.圖像的二維Fourier變換
(1)二維DFT
二維DFT定義公式爲:
計算一個頻域點需要
(2)將二維DFT分解爲兩個一維DFT
Fourier變換的變換核(公式中和
先對二維矩陣的每一列做一維DFT:
再對變換後的矩陣的每一行做一維DFT:
最後以
(3)用一維FFT實現二維FFT
同樣的我們可以用兩個一維FFT實現二維FFT,時間複雜度
function [ mfft2 ] = JCGuoFFT2( data )
h = size(data, 1);
w = size(data, 2);
mfft2 = data;
if power(2, log2(h)) ~= h || power(2, log2(w)) ~= w
disp('JCGuoFFT2 exit: h and w must be the power of 2!')
else
for i = 1 : h
mfft2(i, :) = IterativeFFT(mfft2(i, :));
end
for j = 1 : w
mfft2(:, j) = IterativeFFT(mfft2(:, j));
end
end
end
代碼很簡單,先做FFT行變換再做FFT列變換。之前忘記提到,我這裏實現的都是長度必須是2的次方的Fourier變換,因此有時候會做一些長度規範檢查。
(4)變換結果
經過JCGuoFFT2的二維傅立葉變換,我們可以得到複平面內各個點的複數值,那麼顯示在圖像中需要先求出幅值:
pic1_fft = JCGuoFFT2(double(pic1));
pic1_fft_amp = abs(pic1_fft);
在對幅值做一次log變換得到較好的頻域圖像:
pic1_fft_amp_log = log(1 + pic1_fft_amp);
繪製結果如下圖:
(5)低頻信號移到圖像中心點
由於複數運算的週期特性,圖像的Fourier變換在複平面上是完全對稱的,可以想象平面是由無限多個上圖(右)頻域圖像拼接而成的二維陣列。一般研究頻域圖像是把低頻部分,也就是變換後的邊緣部分移到圖像中心點,Matlab提供fftshift
函數完成平移。
平移的思路有兩個
- 通過Fourier變換平移定理先把原始圖像做變換再做FFT
- 先做FFT後再根據頻域圖像的對稱性做對稱變換
查閱Matlab文檔發現它是採用第二種方法,對圖像做以下子矩陣交換:
那麼我們可以很容易的寫出自己的fftshift
:
function [ after ] = FFTShift( before )
h = size(before, 1);
w = size(before, 2);
after = before;
if power(2, log2(h)) ~= h || power(2, log2(w)) ~= w
disp('FFTShift exit: h and w must be the power of 2!')
else
hh = h / 2;
hw = w / 2;
after(1 : hh, 1 : hw) = before(hh + 1 : h, hw + 1 : w);
after(1 : hh, hw + 1 : w) = before(hh + 1 : h, 1 : hw);
after(hh + 1 : h, 1 : hw) = before(1 : hh, hw + 1 : w);
after(hh + 1 : h, hw + 1 : w) = before(1 : hh, 1 : hw);
end
end
將低頻部分平移到中心點後結果爲:
4.圖像的二維反Fourier變換
(1)一維逆DFT和一維逆FFT
一維離散傅立葉變換的逆變換是將e的指數部分變號,然後整體除以長度N(Fourier變換與逆變換關於符號、係數有很多種組合的定義,但他們都是等價且對稱的。這裏的定義配合Matlab做fft實際效果。):
同樣我們可以根據iDFT的定義推演iFFT的算法,其迭代版本的Matlab實現如下:
function [ ifft_m ] = IterativeIFFT( vec )
clear i;
n = length(vec);
ifft_m = BitReverseCopy(vec);
for s = 1 : log2(n)
m = power(2, s);
wm = exp(2 * pi * i / m);
for k = 0 : m : n - 1
w = 1;
for j = 0 : m / 2 - 1
t = w * ifft_m(k + j + m / 2 + 1);
u = ifft_m(k + j + 1);
ifft_m(k + j + 1) = u + t;
ifft_m(k + j + m / 2 + 1) = u - t;
w = w * wm;
end
end
end
ifft_m = ifft_m ./ n;
end
(2)二維逆FFT
二維逆FFT和二維FFT的思路一致,對所有行和列分別作一次iFFT即可:
function [ mifft2 ] = JCGuoIFFT2( data )
h = size(data, 1);
w = size(data, 2);
mifft2 = data;
if power(2, log2(h)) ~= h || power(2, log2(w)) ~= w
disp('JCGuoIFFT2 exit: h and w must be the power of 2!')
else
for i = 1 : h
mifft2(i, :) = IterativeIFFT(mifft2(i, :));
end
for j = 1 : w
mifft2(:, j) = IterativeIFFT(mifft2(:, j));
end
end
end
(3)逆FFT結果
對之前Rect1.bmp用JCGuoFFT2變換的到的Fourier變換(非shift和log之後、非僅幅度部分)作FFT2逆變換可以直接得到原圖像:
這幅圖有多個結果,可以看title知道每個結果的含義,圖2-1是用JCGuoIFFT2做傅立葉反變換的結果,得到的圖像和原圖像、和Matlab ifft2反變換後的圖像都是一致的。
5.幅頻特性與相頻特性
(1)對振幅和相位單獨做逆FFT
如果我們只把圖像Fourier變換的振幅部分和相位部分單獨做二維逆FFT,可以直觀的感受人眼對圖像幅頻特性和相頻特性的敏感度。
複數
相位角和相位定義爲:
對相位反變換需要在乘以一個係數(我是調出來的,針對圖像,肯定可以自動的做均衡化):
pic2_fft_angle = angle(pic2_fft);
clear i;
tmp = 10000 * exp(i * pic2_fft_angle);
pic2_ifft_angle = uint8(JCGuoIFFT2(tmp));
對振幅和相位單獨做逆FFT結果如下:
(2)人眼敏感度
觀察上圖,幅頻特性主要涵蓋了圖像顏色的分佈,相頻特性主要刻畫了圖像的邊界信息。人眼對圖像的相頻特性更加敏感,看相頻特性能夠大概知道圖像內容。
6.Fourier變換的旋轉定理
(1)Fourier變換旋轉定理
(2)結果
Rect2.bmp是Rect1.bmp旋轉45度的示意圖(注:原Rect2.bmp是二值的,做了預處理,但其本身邊界不平滑,導致效果不太好,但不影響觀察旋轉定理):
我們可以看到幅度FFT正變換和相位FFT你變換都是旋轉了45度,但是幅度FFT逆變換區別較大。