對於灰度圖而言,一個像素點由8個 bit 組成。代替突出灰度級范圍,我們可以突出特定 bit 來為整個圖像外觀作出貢獻,8 bit灰度圖可考慮分層到 1-8 共8個比特平面。很容易理解的是,4個高階比特平面,特別是最后兩個比特平面,包含了在視覺上很重要的大多數數據。而低階比特平面則在圖像上貢獻了更精細的灰度細節。
本篇博客在前面實現了灰度圖的基礎上,進一步探究 bit 平面分層的 FPGA 實現。由於Verilog中都是從0開始算起,所以bit平面我們定義為 0-7 層。
一、MATLAB實現
1 clear all; 2 3 RGB = imread('dollar.jpg'); %讀取圖片文件 4 5 gray = rgb2gray(RGB); %轉換為灰度圖像 6 [ROW,COL,N] = size(gray); %獲得圖片尺寸[高度,長度,維度] 7 8 subplot(3,3,1); 9 imshow(gray,[]); 10 title('原始圖像'); 11 12 for k=1:8 13 for i=1:ROW 14 for j=1:COL 15 tmp(i,j) = bitget(gray(i,j),k);%將RGB(i,j)灰度值分解為二進制串,取第k位 16 end 17 end 18 subplot(3,3,k+1); 19 imshow(tmp,[]); 20 ind = num2str(k-1); 21 imti = ['第',ind,'個位平面']; 22 title(imti); 23 end
點擊運行,得到如下結果:
二、FPGA實現
當看到 MATLAB 實現的代碼時,我們會覺得如果用 Verilog 來實現會非常困難,其實不然,Verilog 是非常適合做這種運算的,關鍵代碼如下所示:
assign bit_data_0 = {16{Y_data[0]}}; //0層 assign bit_data_1 = {16{Y_data[1]}}; //1層 assign bit_data_2 = {16{Y_data[2]}}; //2層 assign bit_data_3 = {16{Y_data[3]}}; //3層 assign bit_data_4 = {16{Y_data[4]}}; //4層 assign bit_data_5 = {16{Y_data[5]}}; //5層 assign bit_data_6 = {16{Y_data[6]}}; //6層 assign bit_data_7 = {16{Y_data[7]}}; //7層
其中 Y_data 是我們獲得 YCbCr 格式的圖像數據之后取出的 8 bit Y分量,即灰度數據。
由於FPGA編譯綜合、上板、傳圖,這一系列的操作實在過於繁瑣,為了讓實驗更加簡便,也為了能夠更直觀的對比各個層數的效果,我引入了一個外部按鍵。下載程序后初始層數為第0層,當按下按鍵時,層數會跟着轉變,直到層數為第7層,之后按下按鍵又回到第0層,循環反復。
此外又引入了一個數碼管顯示模塊,正好可以用來顯示當前層數,不至於混淆,方便和MATLAB上的圖案做對比。
本工程的整體模塊如下所示:
三、上板驗證
唉我的板卡還是有問題,但這個實驗是灰度圖為基礎,總體效果還行,就是背景本來應該是黑色,顯示成了紅色,糟心。
從視頻可以看出,結果和我們的設計相符,各個層面的圖像效果也和 MATLAB 做的一致,實驗成功。
參考資料:
[1] OpenS Lee:FPGA開源工作室(公眾號)
[2] https://blog.csdn.net/jzwong/article/details/52774393