導讀
隨著現科技的發展和社會的進步,信息科技迅速發展,我們可從互聯網、電臺等媒體獲取大量信息?,F代信息的存儲、處理和傳輸變得越來越數字化。在人們的日常生活中,常用的計算機、電視、音響系統、視頻記錄設備、遠程通訊電子設備無一不采用電子系統、數字電路系統。因此,數字技術的應用越來越廣泛。尤其在通信系統和視頻系統中,數字系統尤為突出。而隨著FPGA的出世,數字系統更加受到人們青睞,它為數字系統的設計提供更加便捷的通道,使得數字系統設計可以芯片小型化,電路規模大型化,龐大的邏輯資源,可滿足各種數字系統設計。
隨著社會的發展,科學技術已經應用于各個領域,尤其是醫療領域尤為突出。而在醫療領域中,心臟電信號模擬器手術輔助儀器發展迅速。為了訓練經驗少的醫生熟悉心臟手術的操作過程,而專門開發心臟信號模擬儀器,讓醫生迅速掌握心臟手術操作過程,成為一個經驗豐富心臟手術醫生。
因此,本文將于FPGA平臺,以圖像處理結合信號采集原理,實現醫生在做心臟模擬手術操作導管的過程中,不需要觀察心臟內部情況,即可獲取導管頭在心臟內部信息的功能,采用內窺鏡攝像頭采集視頻和并對導管頭進行跟蹤定位,信號采集技術可將采集到的導管頭在心臟內部觸碰區域的信號采集出來送到專業醫用儀器,進行心臟3D建模。
本設計的實現對醫院培養的經驗少的醫生盡快掌握心臟手術操作流程很有價值,未來將可以培養更多從事心臟手術工作的醫學專業畢業的學生或剛剛從事這個行業的社會醫生。
第三篇內容摘要:本篇會介紹系統調試與測試以及結論,包括系統資源性能調試與分析、系統功能測試等相關內容,還會有VGA的常用分辨率參數表、整體電路圖、主要程序分享等附錄。
六、系統調試與測試
本設計對系統的性能和系統的功能分別進行了測試,性能測試是對FPGA的資源利用情況和運行速度情況進行測試,功能測試有腐蝕算法測試,幀差算法測試,定位功能調試等。
6.1?系統資源性能調試與分析
本設計中,FPGA使用資源如圖6.1所示,組合邏輯資源使用45%,分布式寄存器資源使用23%,總的邏輯宏單元使用52%,存儲器單元使用了15%,一個鎖相環。EP4CE6F17C8共有2個鎖相環,總邏輯宏單元使用資源小于80%。滿足設計任務需求。
圖6.1 EP4CE6F17C8資源使用情況
緩沖模塊穩定運行時鐘200M,可用邏輯分析儀SigalTap驗證,驗證結果如圖6.2和圖6.3所示。
圖6.3 SDRAM傳輸數據圖
結論:設計緩沖長度為512,緩沖節點在256,每次突發256個數據,如圖6.2和圖6.3,在數據有效信號范圍內,傳輸數據正確。而且工作時鐘在200MHz下運行的,基本能滿足多端點圖像數據緩沖需求。
?
6.2?系統功能測試
腐蝕功能測試:腐蝕前可以看到有許多孤立噪聲點在視頻輸出上,輸出結果如圖6.4所示,當進行腐蝕算法處理后孤立噪聲點明顯減少,輸出結果如圖6.5所示。
圖6.4 腐蝕前圖像和幀差結果
圖6.5 腐蝕后圖像和幀差結果
圖6.6 幀差結果
幀差法調試:調試過程中遇到了如下一些問題以及對應的解決方法。
出現問題:
a. 移屏,整個屏幕的圖像向左方移動一部分,圖像未失真,如圖6.6所示。
b. 幀差結果出現混亂,如圖6.6所示。
分析問題及解決方法:
a. 移屏問題原因分析,由于SDRAM緩沖讀寫問題,讀上一幀時,還未來得及將所有數據讀完,下一幀圖像已經來臨,SDRAM寫的優先級高于讀優先級,所以下一幀數據會將上一幀圖像部分數據覆蓋導致每一幀的輸出的圖像都會有偏差而出現移屏。因此,解決方法為調節復位延時參數,使得寫入幀和讀出幀保持在先寫入,延時一段時間后在讀出的關系。
b. 幀差結果混亂原因分析,一開始使用16位RGB565數據做幀差,結果如圖6.6所示,出現混亂,所以使用合成圖像RGB565做幀差導致出現各個通道顏色對應顏色相減溢出到其他通道的情況,所以最終相減的結果出現混亂。因此解決的方法是對其灰度圖像進行幀差,兩幀圖像相減,再對相減的結果取絕對值(注意進行減法操作和取絕對值操作時,防止數據溢出),即為正確幀差結果,如圖6.4和6.5所示。觀察這兩張圖像邊緣輪廓明顯,且有明顯的拖尾現象。
圖6.7 運動目標定位
圖6.8 運動目標定位
圖6.9 運動目標定位
功能測試結果:定位如圖6.7所示,隨著目標物體的運動,運動目標物體有很多坐標點輸出,根據設計任務要求,我們只輸出目標尾端的坐標,下圖右上角為要抓取目標的坐標顯示,可以看到目標所處的位置和輸出的坐標基本符合,圖6.7,圖6.8和圖6.9為運動目標在不同位置的定位結果。
結論
本文通過以下幾種手段解決了幀差算法實現,導管頭定位問題和系統工作性能問題。
1. 乒乓操作將攝像頭采集到的圖像交替存儲到兩個不同的SDRAM存儲空間,通過SDRAM的緩沖作用,在VGA向SDRAM發出請求信號時,同時讀出相鄰兩幀的數據,然后就可做幀差。
2. 導管頭的定位是通過對幀差后的圖像作水平方向和垂直方向的投影,確定出運動目標四條邊界,可確定四個坐標點輸出,但是僅僅有一個坐標點是導管頭的端點,所以計算上邊界與運動物體的交點坐標與左右兩條邊界的距離,判斷導管頭是左上到右下進入攝像頭視覺還是左下到右上進入攝像頭視覺,確定導管兩點坐標輸出,然后再判斷剩余的兩點坐標是否在整張圖像邊界上,確定導管頭坐標輸出。
3. 這個算法設計更多的使用流水算法,使用移位和拼接運算代替乘法器和除法器,提高系統運行速度,減少資源利用率。
附錄A?VGA的常用分辨率參數表
附錄B?主要代碼
?
`include "../sdram_4port_ip/sdram_para.v" module fd_target_location( ref_clk, rst_n, clk_out, //cmos interface CMOS_SCLK, //cmos i2c clock CMOS_SDAT, //cmos i2c data CMOS_VSYNC, //cmos vsync CMOS_HREF, //cmos hsync refrence CMOS_PCLK, //cmos pxiel clock CMOS_XCLK, //cmos externl clock CMOS_DB, //cmos data //VGA port VGA_HSYNC, //horizontal sync VGA_VSYNC, //vertical sync VGAD, //VGA data //SDRAM物理端口 S_CLK, S_CKE, S_NCS, S_NCAS, S_NRAS, S_NWE, S_BA, S_A, S_DB, S_DQM ); input ref_clk; input rst_n; output clk_out; //cmos interface output CMOS_SCLK; //cmos i2c clock inout CMOS_SDAT; //cmos i2c data input CMOS_VSYNC; //cmos vsync input CMOS_HREF; //cmos hsync refrence input CMOS_PCLK; //cmos pxiel clock output CMOS_XCLK; //cmos externl clock input [7:0] CMOS_DB; //cmos data //VGA port output VGA_HSYNC; //horizontal sync output VGA_VSYNC; //vertical sync output [15:0] VGAD; //VGA data //SDRAM物理端口 output S_CLK; output S_CKE; output S_NCS; output S_NCAS; output S_NRAS; output S_NWE; output [`BA-1:0] S_BA; output [`ROW-1:0] S_A; inout [`DQ-1:0] S_DB; output [`DQ/8-1:0] S_DQM; assign clk_out = clk; assign S_DQM = 0; wire vga_clk, camera_clk, clk, sys_rst_n; // wire rst_dly1, soft_rst_n; wire soft_rst_0; wire soft_rst_1; wire soft_rst_2; wire soft_rst_3; wire Config_Done, sdram_init_done; wire sys_we; wire [15:0] sys_data_in; wire frame_valid; wire lcd_request; wire [15:0] lcd_data_1; wire [15:0] lcd_data_2; wire [15:0] lcd_data; wire sdram_wrreq; wire sdram_wrval; wire [`TOTAL_ADDR-1:0] sdram_wraddr; wire [`DQ-1:0] sdram_wdata; wire sdram_wdone; wire sdram_rdreq; wire sdram_rdval; wire [`TOTAL_ADDR-1:0] sdram_rdaddr; wire [`DQ-1:0] sdram_rdata; wire sdram_rdone; wire data_valid; wire write_done_1; wire read_done_1; wire write_done_2; wire read_done_2; wire [23:0] waddr_min_1; wire [23:0] waddr_max_1; wire bound_valid; wire [10:0] lcd_xpos; wire [10:0] lcd_ypos; wire [10:0] x_pos; wire [10:0] y_pos; wire lcd_val; wire [15:0] lcd_dat; wire start; wire [11:0] bcd_x_pos; wire [11:0] bcd_y_pos; wire [10:0] target_x_pos; wire [10:0] target_y_pos; wire char_en; wire [3:0] char_data; reg dval_r1, dval_r2, dval_r3; dcm dcm( .clk (ref_clk), .rst_n (rst_n), .soft_rst_0 (soft_rst_0), .soft_rst_1 (soft_rst_1), .soft_rst_2 (soft_rst_2), .soft_rst_3 (soft_rst_3), .clk_c0 (camera_clk), //camera配置模塊時鐘輸出 .clk_c1 (vga_clk), //vga模塊時鐘輸出 .clk_c2 (clk), //sdram控制器時鐘輸出 .clk_c3 (S_CLK) //sdram端口時鐘 ); I2C_AV_Config I2C_AV_Config ( /*Global clock*/ .iCLK (vga_clk), //25MHz .iRST_N (soft_rst_0), //Global Reset .I2C_SCLK (CMOS_SCLK), //I2C CLOCK .I2C_SDAT (CMOS_SDAT), //I2C DATA .Config_Done (Config_Done),//Config Done .LUT_INDEX (), //LUT Index .I2C_RDATA () //I2C Read Data ); CMOS_Capture ( /*Global Clock*/ .iCLK (camera_clk), //13MHz .iRST_N (soft_rst_2), /*I2C Initilize Done*/ .Init_Done (Config_Done & sdram_init_done), //Init Done /*Sensor Interface*/ .CMOS_RST_N (), //cmos work state(5ms delay for sccb config) .CMOS_PWDN (), //cmos power on .CMOS_XCLK (CMOS_XCLK), // .CMOS_PCLK (CMOS_PCLK), //25MHz .CMOS_iDATA (CMOS_DB), //CMOS Data .CMOS_VSYNC (CMOS_VSYNC), //L: Vaild .CMOS_HREF (CMOS_HREF), //H: Vaild /*Ouput Sensor Data*/ .x_pos (), .y_pos (), .CMOS_HREF_pos (), .CMOS_oCLK (sys_we), //1/2 PCLK .CMOS_oDATA (sys_data_in), //16Bits RGB .CMOS_VALID (frame_valid), //Data Enable .CMOS_FPS_DATA () //cmos fps ); wire corrode_dval_w1; wire corrode_data_w1; wire dilation_dval_w2; wire dilation_data_w2; wire dval_w2; wire data_w2; wire dval_w3; wire [15:0] data_w3; // image_smooth image_smooth( // .clk (CMOS_PCLK), // .rst_n (soft_rst_2), // .dval_i (sys_we), // .data_i (sys_data_in[7:0]), // .dval_o (dval_1), // .data_o (data_1) // ); // median_filter median_filter( // .clk (CMOS_PCLK), // .rst_n (soft_rst_2), // .dval_i (sys_we), // .data_i (sys_data_in[7:0]), // .dval_o (dval_1), // .data_o (data_1) // ); image_corrode image_corrode( .clk (vga_clk), .rst_n (soft_rst_3), .dval_i (lcd_val), .data_i (lcd_dat[0]), .dval_o (corrode_dval_w1), .data_o (corrode_data_w1) ); image_dilation image_dilation( .clk (vga_clk), .rst_n (soft_rst_3), .dval_i (corrode_dval_w1), .data_i (corrode_data_w1), .dval_o (dilation_dval_w2), .data_o (dilation_data_w2) ); //二值圖像投影 projection projection( .clk (vga_clk), .rst_n (soft_rst_3), .dval_i (lcd_val), .data_i (lcd_dat[0]), .x_pos (x_pos), .y_pos (y_pos), .target_x_pos (target_x_pos), .target_y_pos (target_y_pos), .dval_o (dval_w3), .data_o (data_w3) // ); bin_to_bcd u0_bin_to_bcd(.bin(target_x_pos), .bcd(bcd_x_pos)); bin_to_bcd u1_bin_to_bcd(.bin(target_y_pos), .bcd(bcd_y_pos)); char_mac u_char_mac( .clk (vga_clk), .rst_n (soft_rst_3), .start (start), .bcd_x_pos (bcd_x_pos), .bcd_y_pos (bcd_y_pos), .char_en (char_en), .char_data (char_data) ); char_disp u_char_disp ( .clk (vga_clk), .rst_n (soft_rst_3), .char_en (char_en), .char_data (char_data), .move_x_pos (12'd560), .move_y_pos (12'd30), .data_valid_pos (start), .data_valid (dval_w2), //dval_w2 lcd_val dval_w1 dilation_dval_w2 .x_pos (x_pos), .y_pos (y_pos), .data_i ({R[7:3], G[7:2], B[7:3]}), //{R[7:3], G[7:2], B[7:3]} lcd_dat {16{dilation_data_w2}} dilation_data_w2 .data_valid_o (), .data_o (lcd_data) ); //------------------------------------------------------ //將yuv轉換成rgb輸出 wire [7:0] Y, Cb, Cr; wire [7:0] R, G, B; reg [15:0] data_r1; yuv422_yuv444 yuv422_yuv444( .clk (vga_clk), .rst_n (soft_rst_3), .yuv_capture_en (lcd_request), //ahead 2 clock .image_data (lcd_data_1), //lcd_data_1 .Y (Y), .Cb (Cb), .Cr (Cr) ); yuv2rgb yuv2rgb( .clk (vga_clk), //時鐘輸入 .rst (soft_rst_3), //復位輸入 .y_in (Y), //變換前Y分量輸出 .cb_in (Cb), //變換前Cb分量輸出 .cr_in (Cr), //變換前Cr分量輸出 .ena_in (dval_r1), //待變換數據使能,當它為高時,輸入數據有效 .R_out (R), //變換后R分量輸出 .G_out (G), //變換后G分量輸出 .B_out (B), //變換后B分量輸出 .ena_out (dval_w2) //變換后數據使能輸出 ); always @ (posedge vga_clk or negedge soft_rst_3) if(soft_rst_3 == 1'b0) dval_r1 <= 0; else dval_r1 <= lcd_request; always @ (posedge vga_clk or negedge soft_rst_3) if(soft_rst_3 == 1'b0) dval_r2 <= 0; else dval_r2 <= dval_w2; assign start = ~dval_r2 & dval_w2; // Virtual_Camera Virtual_Camera( // .clk (vga_clk), // .rst_n (soft_rst_2), // .sdram_init_done (sdram_init_done), // .dval (sys_we), // .data (sys_data_in) // ); switch_in switch_in( .clk (clk), .rst_n (soft_rst_1), .frame_done (write_done_1), .waddr_min_1 (waddr_min_1), .waddr_max_1 (waddr_max_1) ); switch_out switch_out( .clk (vga_clk), .rst_n (soft_rst_3), .request (lcd_request), .x_pos_i (lcd_xpos), .y_pos_i (lcd_ypos), .x_pos (x_pos), .y_pos (y_pos), .start_o (), .lcd_data_1 (lcd_data_1), .lcd_data_2 (lcd_data_2), .lcd_val (lcd_val), .lcd_data (lcd_dat) //lcd_data ); async_4fifo async_4fifo( .clk (clk), .rst_n (soft_rst_1), .sdram_init_done (sdram_init_done), //sdram初始化完成信號 /*用戶接口*/ /*寫用戶1接口*/ .clk_write_1 (CMOS_PCLK), //vga_clk, CMOS_PCLK .wrreq_1 (sys_we), //sys_we dval_1 .wdata_1 (sys_data_in), //sys_data_in {8'd0, data_1} .write_done_1 (write_done_1), /*參數設置*/ .waddr_min_1 (waddr_min_1), //24'd0 .waddr_max_1 (waddr_max_1), //24'd307200 .wr_length_1 (9'd256), //,這個是緩沖節點 /*讀用戶1接口*/ .clk_read_1 (vga_clk), //vga_clk .rdreq_1 (lcd_request), //lcd_request .rdata_1 (lcd_data_1), //lcd_data lcd_data_1 .read_done_1 (), .data_valid_1 (data_valid), //sdram讀端口同步信號 /*參數設置*/ .raddr_min_1 (24'd0), .raddr_max_1 (24'd307200), .rd_length_1 (9'd256), //,這個是緩沖節點 /*寫用戶2接口*/ .clk_write_2 (CMOS_PCLK), //vga_clk, CMOS_PCLK .wrreq_2 (0), //sys_we .wdata_2 (0), //sys_data_in .write_done_2 (), /*參數設置*/ .waddr_min_2 (24'd0), //24'd307200 .waddr_max_2 (24'd0), //24'd614400 .wr_length_2 (9'd256), //必須添加很重要,這個是緩沖節點 /*讀用戶2接口*/ .clk_read_2 (vga_clk), .rdreq_2 (lcd_request), //lcd_request .rdata_2 (lcd_data_2), //lcd_data lcd_data_2 .read_done_2 (), .data_valid_2 (data_valid), //sdram讀端口同步信號 data_valid /*參數設置*/ .raddr_min_2 (24'd307200), //24'd307200 .raddr_max_2 (24'd614400), //24'd614400 .rd_length_2 (9'd256), //必須添加很重要,這個是緩沖節點 /*寫SDRAM端口*/ .sdram_wrreq (sdram_wrreq), .sdram_wrval (sdram_wrval), .sdram_wraddr (sdram_wraddr), .sdram_wdata (sdram_wdata), .sdram_wdone (sdram_wdone), /*讀SDRAM端口*/ .sdram_rdreq (sdram_rdreq), .sdram_rdval (sdram_rdval), .sdram_rdaddr (sdram_rdaddr), .sdram_rdata (sdram_rdata), .sdram_rdone (sdram_rdone) ); lsm_sdram lsm_sdram( /*全局變量*/ .clk (clk), .rst_n (soft_rst_1), .sdram_init_done (sdram_init_done), /*寫SDRAM端口*/ .sdram_wrreq (sdram_wrreq), .sdram_wrval (sdram_wrval), .sdram_wraddr (sdram_wraddr), .sdram_wdata (sdram_wdata), .sdram_wdone (sdram_wdone), /*讀SDRAM端口*/ .sdram_rdreq (sdram_rdreq), .sdram_rdval (sdram_rdval), .sdram_rdaddr (sdram_rdaddr), .sdram_rdata (sdram_rdata), .sdram_rdone (sdram_rdone), /*SDRAM物理端口*/ .sdram_clk (), .sdram_cke (S_CKE), .sdram_cs_n (S_NCS), .sdram_cas_n (S_NCAS), .sdram_ras_n (S_NRAS), .sdram_we_n (S_NWE), .sdram_ba (S_BA), .sdram_a (S_A), .sdram_dq (S_DB), .sdram_dqm () ); lcd_top lcd_top ( //global clock .clk (vga_clk), //system clock .rst_n (soft_rst_3), //sync reset //lcd interface .lcd_dclk (), //lcd pixel clock .lcd_blank (), //lcd blank .lcd_sync (), //lcd sync .lcd_hs (VGA_HSYNC), //lcd horizontal sync .lcd_vs (VGA_VSYNC), //lcd vertical sync .lcd_en (), //lcd display enable .lcd_rgb (VGAD), //lcd display data //user interface .lcd_request (lcd_request), //lcd data request .lcd_framesync (data_valid), //lcd frame sync .lcd_pos (), .lcd_xpos (lcd_xpos), //lcd horizontal coordinate .lcd_ypos (lcd_ypos), //lcd vertical coordinate .lcd_data (lcd_data) //lcd data ); endmodule
評論
查看更多