Sensor Demoasic (CFA)IP仿真實(shí)例 騰訊鏈接:https://share.weiyun.com/5GQyKKc 百度網(wǎng)盤(pán)鏈接:https://pan.baidu.com/s/1M7PLzRs-yMJv7NFJE8GVAw 提取碼:qr0t ![]() 由于Vivado 19.1以后不再支持Color Filter Array Interpolation IP,轉而由Sensor Demosaic IP替代(實(shí)際實(shí)現的功能相當)。由于我們前面的實(shí)驗都是基于Vivado 16.2版本的,因此在開(kāi)始本實(shí)例之前,請先安裝如下步驟安裝好Vivado 19.1。 Windows 64bit操作系統,可以直接找到at7_img_ex11/tool文件夾下的安裝程序Xilinx_Vivado_SDK_Web_2019.1_0524_1430_Win64.exe,雙擊進(jìn)行Web版本Vivado2019.1安裝。注意安裝過(guò)程必須聯(lián)網(wǎng),該程序運行后邊下載邊安裝(安裝硬盤(pán)需要20G+的空間)。 也可以到Xilinx官方網(wǎng)站(https://www.xilinx.com/support/download.html),下載對應操作系統的Vivado2019.1安裝程序。 借用知乎上的文章(https://zhuanlan.zhihu.com/p/21298545)科普一下CFA。 CFA(Color Filter Array,色彩濾波陣列)也就是我們常說(shuō)的CMOS色彩濾鏡,應該說(shuō)是一個(gè)挺重要,廠(chǎng)商在宣傳的時(shí)候也會(huì )偶爾提及一下的東西。但是對于這個(gè)東西如何起作用,不同的排列又有什么樣的優(yōu)缺點(diǎn),可能很多人就不太清楚了。今天我們就來(lái)討論一下這個(gè)問(wèn)題。 本次討論基于相機中用到的幾種傳感器CFA排列方式,電影機當中用到的Q67之類(lèi),更多的是一種針對性設計(Q67其實(shí)就是旋轉45度的拜耳陣列,菱形像素排列更緊湊,布線(xiàn)長(cháng)度可以短,刷起速度來(lái)更容易,可以認為是電影機的針對性架構,用在相機上其實(shí)意義不大)。 基礎模型——采樣像素與輸出像素 在之前我們簡(jiǎn)單提過(guò)采樣像素與輸出像素的概念,圖像傳感器的空間采樣就是把連續的空間圖像信號轉化為離散的一個(gè)一個(gè)像素,而像素密度代表的就是空間采樣頻率?臻g采樣頻率越高,我們便可以獲取更多的原始圖像高頻細節,從而提升整個(gè)畫(huà)面的細節表現。 當然,如果你看圖的方式是看100%,在同樣的顯示器尺寸和分辨率下,圖像表現還會(huì )受到輸出像素的限制。同樣的采樣像素下,輸出像素越高,則圖像的100%查看細節表現越差。 其實(shí)采樣像素和輸出像素不同的設計在攝影當中可能不多,但是在視頻當中很常見(jiàn)——因為視頻的輸出像素都是固定規格(例如4k就是829萬(wàn)),而采樣像素可以比較靈活——例如索尼A6300,在視頻拍攝模式下就是2000萬(wàn)像素采樣,800萬(wàn)像素輸出。 不過(guò)對于不同的CFA排列方式來(lái)說(shuō),其實(shí)際的采樣和輸出像素差別也比較大——尤其是CFA是為了色彩輸出而設計,在平面上要放置3種顏色的濾色片,每一種顏色必然都存在空間欠采樣的現象。至于影響如何,我們接下來(lái)對每一種CFA來(lái)進(jìn)行一下簡(jiǎn)單分析。 最簡(jiǎn)單的——無(wú)色彩濾鏡 只能輸出黑白圖像,最典型的比如徠卡的法師機Leica M Monochrome~
![]() 無(wú)色彩濾鏡的情形分析起來(lái)也是相當簡(jiǎn)單,沒(méi)有CFA造成的采樣頻率損失,采樣像素就等于輸出像素。缺點(diǎn)就是這種結構只能拍攝黑白圖片,無(wú)法顯示色彩。 最常用的——拜耳陣列 拜耳陣列一般被俗稱(chēng)為“馬賽克傳感器”,因為這種排列方式看起來(lái)的確有點(diǎn)像花花綠綠的馬賽克晶格:
![]() 很明顯可以看到拜耳陣列是由一行RGRGRG……和一行BGBGBG……交錯排列而成,每一個(gè)像素點(diǎn)只能讀取單獨的顏色信息。其中綠色像素的采樣頻率是輸出像素的1/2,紅、藍色像素的采樣頻率是輸出像素的1/4,故有拜耳陣列傳感器的分辨率是由綠色像素決定的這一說(shuō)法。 拜耳陣列傳感器采樣生成的圖像要輸出我們常見(jiàn)的全色彩圖像必須經(jīng)過(guò)反馬賽克運算——但這跟我們平時(shí)俗稱(chēng)的名字“猜色”的字面意義不同,拜耳陣列的顏色并不是猜的,而是每個(gè)2×2方塊經(jīng)過(guò)9次矩陣運算計算出來(lái)的,也就是說(shuō)不存在猜這回事,每個(gè)像素的顏色其實(shí)是一個(gè)確定值(矩陣運算是線(xiàn)性運算,這并不是一個(gè)混沌系統)。但沒(méi)有爭議的是拜耳陣列確實(shí)存在欠采樣問(wèn)題,這也使得它會(huì )出現摩爾紋和偽色(摩爾紋出現的原因就是輸入信號的最高頻率成分超過(guò)了傳感器的奈奎斯特極限,也就是說(shuō)傳感器的高頻采樣能力存在一些不足),100%查看時(shí)的畫(huà)質(zhì)也不是特別理想。 但是,看一個(gè)結構或者說(shuō)架構是否強勢,一個(gè)很重要的東西其實(shí)是成熟度與可擴增性——有時(shí)候一些暴力美學(xué)解決起問(wèn)題來(lái)反而十分優(yōu)雅。 拜耳陣列就是這么一個(gè)典型,簡(jiǎn)單的結構與成熟的工藝讓它堆起像素來(lái)十分容易,只要底下的光電管能跟得上,分分鐘3000萬(wàn)、4000萬(wàn)、5000萬(wàn)……接下來(lái)感覺(jué)應該就得上億了(135畫(huà)幅)。雖然結構本身存在欠采樣問(wèn)題,但畢竟架不住擁兵十萬(wàn)坐糧成山…理論上來(lái)說(shuō),當拜耳陣列傳感器的實(shí)際像素數超越無(wú)CFA,或者X3這種傳感器的輸出像素2.8倍的時(shí)候,在輸出同樣大小的圖片時(shí)便可以獲取超越全色傳感器的分辨率和100%查看畫(huà)質(zhì)。 CFA雖然解決了像素問(wèn)題,卻帶來(lái)了新的色彩問(wèn)題。在CMOS/CCD Image Sensor采集過(guò)來(lái)的Bayer Raw數據,每個(gè)像素只提供一個(gè)色彩的顏色數據(Red、Green或Blue)。但是,最終顯示或還原每個(gè)像素的色彩信息,卻是每個(gè)像素都需要具備R、G、B三色數據。怎么解決這個(gè)問(wèn)題?沒(méi)錯,色彩插值!在CFA發(fā)明之前,前人也的確是通過(guò)每個(gè)像素分別擺放R、G、B三個(gè)濾光片來(lái)獲得每個(gè)像素的R、G、B數據。但是,聰明的Kodak科學(xué)家Bryce Bayer發(fā)現通過(guò)CFA方式進(jìn)行后期插值可以幾乎不失真的還原每個(gè)像素的R、G、B信息。用最節能環(huán)保的方式實(shí)現性能相當的產(chǎn)品,這才是工程開(kāi)發(fā)的最高境界。 一種常見(jiàn)的Bayer Raw圖像的色彩排布如圖所示,插值的基本原理很簡(jiǎn)單,每個(gè)像素沒(méi)有采集到的色彩,可以通過(guò)周邊的對應色彩值進(jìn)行一定的運算獲得。
![]() 在Xilinx Vivado中,提供了Sensor Demosaic IP用于實(shí)現CFA的插值運算。IP內部結構大體如圖所示。多行圖像的緩存,對不同像素值位置的判斷,相應臨近色彩數據的運算處理,邊界上還需要特殊的判斷和處理,整個(gè)控制上還是略有些復雜。特權同學(xué)早年由于項目需要,做過(guò)一個(gè)CFA插值的實(shí)現,各種分支判斷處理,極費腦力。好在,今天Xilinx提供的這個(gè)Sensor Demosaic IP省去了大家大量的時(shí)間和精力。
![]() 在Matlab中,調用函數demosaic可以實(shí)現Bayer RAW轉RGB圖像。運行文件夾at7_img_ex11\matlab下的Matlab腳本beyer2RGB_matlab.m,可以實(shí)現Bayer Raw格式的圖像mandi_bayer_raw.tif轉換為RGB圖像mandi_rgb.tif。源碼如下。 clc;clear `all;close all; %load origin bayer raw image I = imread('mandi_bayer_raw.tif'); %convert a bayer raw image to RGB image J = demosaic(I,'bggr'); %write image as .tif imwrite(J,'mandi_rgb.tif'); %show origin bayer raw and RGB image figure(1) subplot(1,2,1);imshow(I); title('Origin BayerRaw Image') subplot(1,2,2);imshow(J); title('RGB Image'); Bayer Raw圖像和RGB色彩插值后的圖像比對如下。 ![]() 對于IP的添加配置和詳細接口定義,大家可以查看官方文檔pg286-v-demosaic.pdf(存放在matlab文件夾下)。這里做簡(jiǎn)單的說(shuō)明。 打開(kāi)Vivado,在IP Catalog窗口Search中輸入sensor,可以在Vivado Repository à Video & Image Processing下看到Sensor Demoasic的IP核,雙擊它。
![]() 彈出配置頁(yè)面如下。設定采樣時(shí)鐘數(Samples per Clock)為1,數據位寬(Maximum Data Width)為8(bit),最大列分辨率(Maximum Number of Columns)為8192(pixel),最大行分辨率(Maximum Number of Rows)為4320,插值方式選擇高分辨率插值法(High Resolution Interpolation)。點(diǎn)擊OK完成配置。
![]() 點(diǎn)擊Generate按鈕生成IP文件,可能需要較長(cháng)時(shí)間。
![]() 添加好IP后,可以在IP Sources中找打新產(chǎn)生的v_demosaic_0的IP,展開(kāi)Instantiation Template后,找到Verilog的例化模板v_demosaic_0.veo。
![]() .s_axi_CTRL_AWADDR(s_axi_CTRL_AWADDR), // input wire [5 : 0] s_axi_CTRL_AWADDR .s_axi_CTRL_AWVALID(s_axi_CTRL_AWVALID), // input wire s_axi_CTRL_AWVALID .s_axi_CTRL_AWREADY(s_axi_CTRL_AWREADY), // output wire s_axi_CTRL_AWREADY .s_axi_CTRL_WDATA(s_axi_CTRL_WDATA), // input wire [31 : 0] s_axi_CTRL_WDATA .s_axi_CTRL_WSTRB(s_axi_CTRL_WSTRB), // input wire [3 : 0] s_axi_CTRL_WSTRB .s_axi_CTRL_WVALID(s_axi_CTRL_WVALID), // input wire s_axi_CTRL_WVALID .s_axi_CTRL_WREADY(s_axi_CTRL_WREADY), // output wire s_axi_CTRL_WREADY .s_axi_CTRL_BRESP(s_axi_CTRL_BRESP), // output wire [1 : 0] s_axi_CTRL_BRESP .s_axi_CTRL_BVALID(s_axi_CTRL_BVALID), // output wire s_axi_CTRL_BVALID .s_axi_CTRL_BREADY(s_axi_CTRL_BREADY), // input wire s_axi_CTRL_BREADY .s_axi_CTRL_ARADDR(s_axi_CTRL_ARADDR), // input wire [5 : 0] s_axi_CTRL_ARADDR .s_axi_CTRL_ARVALID(s_axi_CTRL_ARVALID), // input wire s_axi_CTRL_ARVALID .s_axi_CTRL_ARREADY(s_axi_CTRL_ARREADY), // output wire s_axi_CTRL_ARREADY .s_axi_CTRL_RDATA(s_axi_CTRL_RDATA), // output wire [31 : 0] s_axi_CTRL_RDATA .s_axi_CTRL_RRESP(s_axi_CTRL_RRESP), // output wire [1 : 0] s_axi_CTRL_RRESP .s_axi_CTRL_RVALID(s_axi_CTRL_RVALID), // output wire s_axi_CTRL_RVALID .s_axi_CTRL_RREADY(s_axi_CTRL_RREADY), // input wire s_axi_CTRL_RREADY .ap_clk(ap_clk), // input wire ap_clk .ap_rst_n(ap_rst_n), // input wire ap_rst_n .interrupt(interrupt), // output wire interrupt .s_axis_video_TVALID(s_axis_video_TVALID), // input wire s_axis_video_TVALID .s_axis_video_TREADY(s_axis_video_TREADY), // output wire s_axis_video_TREADY .s_axis_video_TDATA(s_axis_video_TDATA), // input wire [7 : 0] s_axis_video_TDATA .s_axis_video_TKEEP(s_axis_video_TKEEP), // input wire [0 : 0] s_axis_video_TKEEP .s_axis_video_TSTRB(s_axis_video_TSTRB), // input wire [0 : 0] s_axis_video_TSTRB .s_axis_video_TUSER(s_axis_video_TUSER), // input wire [0 : 0] s_axis_video_TUSER .s_axis_video_TLAST(s_axis_video_TLAST), // input wire [0 : 0] s_axis_video_TLAST .s_axis_video_TID(s_axis_video_TID), // input wire [0 : 0] s_axis_video_TID .s_axis_video_TDEST(s_axis_video_TDEST), // input wire [0 : 0] s_axis_video_TDEST .m_axis_video_TVALID(m_axis_video_TVALID), // output wire m_axis_video_TVALID .m_axis_video_TREADY(m_axis_video_TREADY), // input wire m_axis_video_TREADY .m_axis_video_TDATA(m_axis_video_TDATA), // output wire [23 : 0] m_axis_video_TDATA .m_axis_video_TKEEP(m_axis_video_TKEEP), // output wire [2 : 0] m_axis_video_TKEEP .m_axis_video_TSTRB(m_axis_video_TSTRB), // output wire [2 : 0] m_axis_video_TSTRB .m_axis_video_TUSER(m_axis_video_TUSER), // output wire [0 : 0] m_axis_video_TUSER .m_axis_video_TLAST(m_axis_video_TLAST), // output wire [0 : 0] m_axis_video_TLAST .m_axis_video_TID(m_axis_video_TID), // output wire [0 : 0] m_axis_video_TID .m_axis_video_TDEST(m_axis_video_TDEST) // output wire [0 : 0] m_axis_video_TDEST ); 對IP的引出接口,簡(jiǎn)單說(shuō)明如下。 ap_clk為同步時(shí)鐘信號;ap_rst_n為低電平有效的復位信號;interrupt為中斷信號,目前保留不用。 s_axi_CTRL_*為AXI配置接口,通過(guò)這個(gè)接口,可以實(shí)現IP核的分辨率設定、Bayer Raw輸入模式設定和開(kāi)關(guān)等設定。上電初始,必須通過(guò)這個(gè)接口做配置后IP核才能工作。 s_axis_video_*為輸入IP的Bayer Raw數據流以及控制信號。m_axis_video_*為輸出IP的經(jīng)過(guò)轉換的RGB數據流以及控制信號。 信號的使用可以參考工程的仿真測試腳本at7_bayer2rgb_sim.v。詳細信號定義可以參考文檔pg286-v-demosaic.pdf。 首先,Matlab下運行at7_img_ex11\matlab文件夾下的腳本image_txt_generation.m,將Bayer Raw圖像mandi_bayer_raw.tif生成16進(jìn)制數據存儲到image_in_hex.txt文本中。 復制image_in_hex.txt文本,粘貼到at7.sim文件夾下。 Vivado19.1版本中打開(kāi)工程at7_img_ex11,確認at7_bayer2rgb_sim.v模塊為仿真top module,點(diǎn)擊Run Simulation啟動(dòng)仿真。整個(gè)過(guò)程編譯時(shí)間較長(cháng),需要耐心等待。 運行仿真后,波形如圖所示。
![]() 仿真運行結束后,在文件夾at7_img_ex11\at7.sim\sim_1\behav\xsim下生成FPGA輸出的RGB色彩數據在文本FPGA_CFA_Image.txt中。 運行matlab文件夾下的腳步draw_image_from_FPGA_result.m,可以將FPGA_CFA_Image.txt文本的圖像和Matlab產(chǎn)生的圖像一同繪制出來(lái)。 clc;clear `all;close all; IMAGE_WIDTH = 3039; IMAGE_HIGHT = 2014; IMAGE_SIZE = 3*IMAGE_WIDTH*IMAGE_HIGHT; %load CFA image data from txt fid1 = fopen('FPGA_CFA_Image.txt', 'r'); img = fscanf(fid1,'%x'); fclose(fid1); img = uint8(img); img2 = reshape(img,3,IMAGE_WIDTH,IMAGE_HIGHT); img3 = permute(img2,[3,2,1]); I = uint8(img3); imwrite(I,'FPGA_CFA_Image.tif'); I = imread('FPGA_CFA_Image.tif'); %load origin bayer raw image J = imread('mandi_rgb.tif'); %show origin bayer raw and RGB image figure(1) subplot(1,2,1);imshow(J); title('RGB Image with Matlab') subplot(1,2,2);imshow(I); title('RGB Image with FPGA'); FPGA和Matlab分別做插值產(chǎn)生的RGB圖像比對如下。肉眼看上去基本效果相當。
![]() |