基于FPGA的圖像FFT濾波處理 騰訊鏈接:https://share.weiyun.com/5GQyKKc 百度網盤鏈接:https://pan.baidu.com/s/1M7PLzRs-yMJv7NFJE8GVAw 提取碼:qr0t ![]() 關于傅里葉變換,這么一個神奇的變換,其基本原理和應用在教科書、網絡上漫天飛舞,這里就不贅述了,以免有湊字數的嫌疑。前面的例子我們已經使用Matlab和Vivado的FFT IP核進行了初步的驗證,掌握的FFT/IFFT IP核的脾氣,那么接下來我們要玩點真的了,基于我們STAR/SF-AT7板采集到的MT9V034圖像,我們要進行每個行的FFT和IFFT變換,當然,生成的FFT結果我們可以進行必要的濾波,然后再進行IFFT查看濾波效果。 使用at7_img_ex06\matlab文件夾下的Matlab源碼image_1D_fft_ifft.m或L1024_of_image_1D_fft_ifft.m(將640個點擴展為1024個點進行FFT變換,擴展的點以0填充,模擬FPGA的FFT IP核實際工作狀況),對測試圖像test進行FFT變換,進行必要的濾波,然后IFFT逆變換。 測試圖像為彩色圖像,原始圖像如下。
![]() 首先進行彩色轉灰度的變換,灰度圖像如下。
![]() 提取出其中1行進行FFT變換后的圖像頻譜如下。很明顯,大部分高頻分量集中在前面幾個點,而后面的點幾乎頻率都很小。
![]() 放大頻譜圖,看到細節如下。這里繪制了一條取值為300的直線,有將近50%的頻譜集中在這條線以下。若是做圖像壓縮,其實我們可以把這些低頻分量忽略了,那么數據量可能會大大降低,當然了,副作用是圖像可能會有一定程度的失真,有失必有得嘛。濾除這些低頻分量,也會使圖像更銳一些。話說做FFT變換的目的可遠不止這些,在一些特殊的應用場景中,我們總是希望從原始圖像中提取出一些和應用直接相關的特征信息,那么做了FFT后的圖像常常非常有益于這些操作。為了演示,這里我們的代碼里面就將這些低于300的點都濾除,即取0。
![]() 從頻譜圖上看,如圖所示,右側的濾波后明顯圖像偏黑(很多值取0了)了。
![]() 我們重新把原圖放到這里,和FFT濾波并IFFT以后的圖像做比對,圖像整體仍然保持不變,但是查看細節,可以發現處理后的圖像明顯銳了一些。
![]() ![]() Matlab源碼如下: clc;clear `all;close all; IMAGE_WIDTH = 640; IMAGE_HIGHT = 480; %load origin image %I = imread('Lena_gray_niose.bmp'); I = imread('test.bmp'); I = rgb2gray(I); %fclose(fid1); %% output image data in hex file raw_image = reshape(I, IMAGE_HIGHT, IMAGE_WIDTH); raw_image = raw_image'; fid2 = fopen('image_in_hex.txt', 'wt'); fprintf(fid2, '%04x\n', raw_image); fid2 = fclose(fid2); %show origin image figure,imshow(I); title('Original image'); %1D fft base on every image line II = zeros(IMAGE_HIGHT,1024); J = zeros(IMAGE_HIGHT,1024); for i = 1:IMAGE_HIGHT for j = 1:IMAGE_WIDTH II(i,j) = I(i,j); end J(i, ![]() ![]() ![]() end %show 1 linefft result t1 = (0:IMAGE_WIDTH); % Time vector line = ones(IMAGE_WIDTH) * 200; figure; plot(t1(1:IMAGE_WIDTH),abs(J(50,1:IMAGE_WIDTH)),t1(1:IMAGE_WIDTH),line(1:IMAGE_WIDTH)) title(['1 line image in the Frequency Domain']) %show fft of origin image figure,imshow(log(abs(J)),[]); title('1D fft image base on every image line'); %colormap(jet(64)),colorbar; %fftfiter J(abs(J) < 300) = 0; %J(abs(J) > 1000) = 1000; %show fft of fft filter image figure,imshow(log(abs(J)),[]); title('1D fft image after filter'); %1D ifft base on every image line K = zeros(IMAGE_HIGHT,1024); for i = 1:IMAGE_HIGHT K(i, ![]() ![]() end KK = zeros(IMAGE_HIGHT,IMAGE_WIDTH); for i = 1:IMAGE_HIGHT for j = 1:IMAGE_WIDTH KK(i,j) = K(i,j); end end %show ifft image figure,imshow(KK,[]) title('1D ifft image'); 在Sources面板中,展開Simulation Sources à sim_1,將sim_fft.v文件設置為top module。同樣是對前面的測試圖像,經過FFT和IFFT變換后存儲在image_view0.txt文本中(仿真測試結果位于at7_img_ex06\at7.sim\sim_1\behav文件夾下)。為了確認FFT和IFFT IP核運算的精度和效果,這里沒有做任何的濾波處理。
![]() 使用draw_image_from_FPGA_result.m腳本(at7_img_ex06\matlab文件夾下)導入image_view0.txt文本的圖像,和原始圖像比對如下所示。看到圖像幾乎沒有任何失真。
![]() 工程文件夾at7_img_ex06\zstar.srcs\sources_1\new下的image_fft_filter.v模塊以及3個子模塊image_fft_controller.v、image_filter.v和image_ifft_controller.v實現了圖像的FFT變換、濾波和IFFT變換處理。FPGA設計的功能框圖如下。
![]() image_fft_controller.v模塊例化FFT IP核,將采集的圖像留以行為單位輸入到FFT IP核,輸出FFT頻域數據。 image_filter.v模塊對FFT頻域數據計算絕對值并進行必要的濾波處理,假設FFT結果的實部值為a,虛部值為b,那么其絕對值abs =sqrt(a^2+b^2)。如下代碼,注釋部分可以濾除低頻分量,當前例程中為了驗證FFT和IFFT變換后精度沒有損失,未作濾波。 always @(posedgeclk or negedgerst_n) if(!rst_n) begin o_image_filter_data_image<= 20'd0; o_image_filter_data_real<= 20'd0; end /*else if(sqrt_fft[19:0] < 20'd300) begin //此處可以做必要的高頻或低頻濾波處理 o_image_filter_data_image<= 20'd0; o_image_filter_data_real<= 20'd0; end*/ else begin o_image_filter_data_image<= r_image_fft_data_image[TOTAL_LATENCY-1]; o_image_filter_data_real<= r_image_fft_data_real[TOTAL_LATENCY-1]; end image_ifft_controller.v模塊將濾波處理后的FFT結果進行IFFT變換,圖像轉回時域值,供后續模塊緩存DDR3并顯示。 AT7_Xilinx開發板(USB3.0+LVDS)資料共享 騰訊鏈接:https://share.weiyun.com/5GQyKKc 百度網盤鏈接:https://pan.baidu.com/s/1M7PLzRs-yMJv7NFJE8GVAw 提取碼:qr0t |