基於 FPGA 的圖像邊緣檢測

来源:http://www.cnblogs.com/aslmer/archive/2016/08/18/5779079.html
-Advertisement-
Play Games

本文主要內容是實現圖像的邊緣檢測功能 目錄 mif文件的製作 受資源限制,將圖片像素定為 160 * 120,將圖片數據製成 mif 文件,對 rom ip 核進行初始化。mif文件的製作方法網上有好多辦法,因此就不再敘述了,重點說mif文件的格式。 1、mif文件的格式為: 調用ip 核生成 ro ...


本文主要內容是實現圖像的邊緣檢測功能


目錄

  1. mif文件的製作
  2. 調用 ip 核生成rom以及在 questasim 模擬註意問題
  3. 灰度處理
  4. 均值濾波
  5. sobel邊緣檢測
  6. 圖片的顯示   
  7. 結果展示                                                                                                                                                                                                       

mif文件的製作

受資源限制,將圖片像素定為 160 * 120,將圖片數據製成 mif 文件,對 rom ip 核進行初始化。mif文件的製作方法網上有好多辦法,因此就不再敘述了,重點說mif文件的格式。 

1、mif文件的格式為:

 1 WIDTH=16 ;    //數據位寬
 2 DEPTH=19200 ;   // rom 深度即圖片像素點的個數
 3 ADDRESS_RADIX=UNS ;   //地址數據格式
 4 DATA_RADIX=BIN ;   //數據格式
 5 CONTENT
 6 BEGIN
 7 0:1010110011010000 ;     // 地址 :數據 ;註意格式要和上面定義的保持統一
 8 1:1010110011010000 ;
 9 2:1010010010110000 ;
10 ......
11 19198:1110011011111001 ;
12 19199:1110011011011000 ;
13 END;

 


調用ip 核生成 rom 以及在 questasim 模擬註意問題

這部分內容已經在上篇博文中詳細描述過,詳情請見http://www.cnblogs.com/aslmer/p/5780107.html

 


 

灰度處理

任何顏色都由紅、綠、藍三原色組成,假如原來某點的顏色為( R,G,B )那麼,我們可以通過下麵幾種方法,將其轉換為灰度:
  • 浮點演算法:Gray=0.299R+0.587G+0.114B
  • 平均值法:Gray=(R+G+B)/3;
  • 僅取單色(如綠色):Gray=G;
將計算出來的Gray值同時賦值給 RGB 三個通道即RGB為(Gray,Gray,Gray),此時顯示的就是灰度圖。通過觀察調色板就能看明瞭。 通過觀察可知,當RGB三個通道的值相同時即為灰色,Gray的值越大,顏色越接近白色,反之越接近黑色(這是我自己的理解,不嚴謹錯誤之處請大神指正)。 這是線上調色板網址,可以進去自己研究一下。http://tool.chinaz.com/tools/selectcolor.aspx

--------------------------------------------------------------------------------------------------------------------

此次我採用是浮點演算法來實現灰度圖的,我的圖片數據是RGB565 格式 ,

難點: 如何進行浮點運算。

思路:先將數據放大,然後再縮小。

例如: Gray=0.299R+0.587G+0.114B轉化為 Gray=(77R+150G+29B)>>8 即可,這裡有一個技巧,若 a 為 16 位即 a [15:0],那麼 a>>8 與 a [15:8]是一樣的。 核心代碼如下:
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       red_r1   <= 0 ;  
       green_r1 <= 0 ;
       blue_r1  <= 0 ;
    end
    else begin
       red_r1   <= red   * 77 ;        //放大後的值
       green_r1 <= green * 150;
       blue_r1  <= blue  * 29 ;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        Gray <= 0;    // 三個數之和
    end
    else begin
        Gray <= red_r1 + green_r1 + blue_r1;        
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       post_data_in <= 0;  //輸出的灰度數據
    end
    else begin
       post_data_in <= { Gray[13:9], Gray[13:8], Gray[13:9] };//將Gray值賦值給RGB三個通道
    end
end
 

均值濾波

均值濾波的原理

http://blog.csdn.net/hhygcy/article/details/4325304 (此處引用 hhygcy 的文章)

難點:如何生成 3*3 的像素陣列。

我們可以利用 ip 核生成移位寄存器 ,方法與 ip 核 生成 rom 一樣,詳情見目錄 2 因此不再贅述 。

模擬波形如下 row_1 , row_2 , row_3 是指圖像的第一、二、三行的數據,Per_href 是行有效信號(受VGA時序的啟發,從 rom 中讀取數據時設計了行有效和場有效的控制信號,事半功倍,有了利於模擬查錯和數據的控制)。從 3 開始就出現了3*3 的像素陣列,這時候就可以求取周圍 8 個像素點的平均值,進行均值濾波。

核心代碼如下:

reg [5:0]p_11,p_12,p_13;  // 3 * 3 捲積核中的像素點
reg [5:0]p_21,p_22,p_23;
reg [5:0]p_31,p_32,p_33;
reg [8:0]mean_value_add1,mean_value_add2,mean_value_add3;//每一行之和


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        {p_11,p_12,p_13} <= {5'b0,5'b0,5'b0}   ;
        {p_21,p_22,p_23} <= {15'b0,15'b0,15'b0};
        {p_31,p_32,p_33} <= {15'b0,15'b0,15'b0};
    end
    else  begin
     if(per_href_ff0==1&&flag_do==1)begin
        {p_11,p_12,p_13}<={p_12,p_13,row_1};
        {p_21,p_22,p_23}<={p_22,p_23,row_2};
        {p_31,p_32,p_33}<={p_32,p_33,row_3};
     end
     else begin
         {p_11,p_12,p_13}<={5'b0,5'b0,5'b0};
         {p_21,p_22,p_23}<={5'b0,5'b0,5'b0}
         {p_31,p_32,p_33}<={5'b0,5'b0,5'b0}
     end
   end
end



always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        mean_value_add1<=0;
        mean_value_add2<=0;
        mean_value_add3<=0;
    end
    else if(per_href_ff1)begin
        mean_value_add1<=p_11+p_12+p_13;
        mean_value_add2<=p_21+   0   +p_23;
        mean_value_add3<=p_31+p_32+p_33;
    end
end

wire [8:0]mean_value;//8位數之和
wire [5:0]fin_y_data; //平均數,除以8,相當於左移三位。

assign mean_value=mean_value_add1+mean_value_add2+mean_value_add3;
assign fin_y_data=mean_value[8:3]; 

 


 

sobel 邊緣檢測 

邊緣檢測的原理

該運算元包含兩組 3x3 的矩陣,分別為橫向及縱向,將之與圖像作平面捲積,即可分別得出橫向及縱向的亮度差分近似值。A代表原始圖像的 3*3 像素陣列,Gx及Gy分別代表經橫向及縱向邊緣檢測的圖像,其公式如下:

圖像的每一個像素的橫向及縱向梯度近似值可用以下的公式結合,來計算梯度的大小。

 

如果梯度G大於某一閥值則認為該點(x,y)為邊緣點。

-------------------------------------------------------------------------------------------------------------------

用的是 邊緣檢測演算法。

難點:(1)掌握了 3*3 像素陣列,Gx 與 Gy 就很好計算了 (註意問題:為了避免計算過程中出現負值,所以將正負值分開單獨計算,具體見代碼)

        (2)G的計算需要開平方,如何進行開平方運算

Quartus 提供了開平方 ip 核,因此我們直接調用就好了 。

代碼:

reg [8:0] p_x_data ,p_y_data ;  // x 和 y 的正值之和
reg [8:0] n_x_data ,n_y_data ; // x 和 y 的負值之和
reg [8:0] gx_data  ,gy_data  ; //最終結果

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       p_x_data <=0;
       n_x_data <=0;
       gx_data   <=0;
    end
    else if(per_href_ff1==1) begin 
        p_x_data <= p_13 + (p_23<<1) + p_33 ;
        n_x_data <= p_11 + (p_12<<1 )+ p_13 ;
        gx_data   <= (p_x_data >=n_x_data)? p_x_data - n_x_data : n_x_data - p_x_data ; 
    end
    else begin
         p_x_data<=0;
         n_x_data<=0;
         gx_data <=0;
    end  
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
       p_y_data <=0;
       n_y_data <=0;
       gy_data   <=0;
    end
    else if(per_href_ff1==1) begin
        p_y_data <= p_11 + (p_12<<1) + p_13 ;
        n_y_data <= p_31 + (p_32<<1) + p_33 ;
        gy_data   <= (p_y_data >=n_y_data)? p_y_data - n_y_data : n_y_data - p_y_data ; 
    end
    else begin
        p_y_data <=0;
        n_y_data <=0;
        gy_data   <=0;
   end
end

//求平方和,調用ip核開平方
reg [16:0] gxy; // Gx 與 Gy 的平方和
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        gxy<=0;
    end
    else begin
        gxy<= gy_data* gy_data + gx_data* gx_data ;
    end
end

wire [8:0] squart_out ; 
altsquart  u1_altsquart (     //例化開平方的ip核
    .radical (gxy),
    .q       (squart_out),  //輸出的結果
    .remainder()
                       );

//與閾值進行比較
reg [15:0] post_y_data_r;
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        post_y_data_r<=16'h00;
    end
    else if(squart_out>=threshold)
         post_y_data_r<=16'h00  ;
    else
         post_y_data_r<=16'hffff  ;
    
end

 


 

圖片的顯示

本來是想用 VGA 來顯示圖片的,由於條件的限制沒能實現,最終只能將處理完的數據輸出保存在 .txt 文件中,然後藉助好友寫的網頁進行顯示。

難點:(1) 如何將數據流輸出保存到 .txt 文件中。

        (2) 網頁的使用及註意事項

在testbench裡加入下麵所示代碼即可將圖片數據保存到 .txt 文本

代碼如下:

     integer w_file;  
     initial
     w_file = $fopen("data_out_3.txt");   //保存數據的文件名

     always @(posedge clk or negedge rst_n)  
     begin  
      if(flag_write==1&&post_href==1)//根據自己的需求定義
        $fdisplay(w_file,"%b",post_y_data);   
      end      

------------------------------------------------------------------------------------------------

網頁的界面如下,將參數設置好以後就可以顯示圖片。

下載鏈接  http://files.cnblogs.com/files/aslmer/aggregrate.zip

註意:由於此網站是量身定做的,所以只能顯示數據格式為RGB565的16位二進位的數才能正確顯示,註意不能有分號,正確格式示例如下,必須嚴格遵守

 


 

 結果展示

 

1 原圖

   2 灰度圖

    3 均值濾波

4 邊緣檢測 閾值為5

  

5  閾值為 10

 

6  閾值為 16       

小結:均值濾波處理後的圖片有明顯的黑邊,產生這一現象的原因就是生成 3*3 像素矩陣和取像素值時數據有損失造成的,但是這也是可以優化的,後續我會繼續努力不斷完善。本次只是簡單對一幅圖像進行邊緣檢測,我的後續目標是實現圖片的實時處理,這又需要學習很多東西了,SDRAM、攝像頭驅動等等等,越學習越發現自己知道的實在是太少了,永遠在路上,學無止境。希望我的分享能夠幫助一些和我一樣熱愛 FPGA 圖像處理的朋友。

                                                                                                                                                                   

                                                                                                                                                                                  每天進步一點點,開心就好

                                                                                                                                                                                       aslmer

轉載請註明出處 http://www.cnblogs.com/aslmer/p/5779079.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在C#實現類似Typedef的所有功能 Typedef這個關鍵字,是比較好用的東西,因為有時候我們需要使用一些別名來幫助我們記憶某些結構體或者類的共用。(個人覺得這是C與C++唯一能吸引我的東西)為了能夠實現這個想法,我們可以使用下列方法。 1.使用using語句進行別名,這個方法適合針對結構體。 ...
  • ASP.NET Boilerplate,簡稱ABP 詳細深入:可以參考如下文章 http://www.cnblogs.com/mienreal/p/4528470.html http://www.cnblogs.com/farb/ 開始前你將要跑起第一個abp程式 可是發現怎麼都運行不起來。。。。 ...
  • 最前面的話:Smobiler是一個在VS環境中使用.Net語言來開發APP的開發平臺,也許比Xamarin更方便 ...
  • 如題,要實現一個如下的列表,該如何實現? 在設計過程中,會遇到如下問題: 1、ListBox中ListBoxItem的模板設計 2、ListBox中ListBoxItem的模板容器設計 3、ListBox本身的模板設計 4、ListBox本身的焦點樣式 下麵我們依次來解決這些問題: 1、子模板 2、 ...
  • 前端: 後端: ...
  • C#過濾html標簽 在項目中遇到這樣一個需求,需要將一段html轉換為一般文本返回,萬能的正則表達式來了。 正則表達式來拯救你,代碼如下: 1 public static string Html2Text(string htmlStr) 2 3 { 4 5 if (String.IsNullOrE ...
  • 二、activiti.cfg.xml的其他bean節點配置 2.1 新特性:Job Executor和Async Executor 從5.17.0版本的activiti開始提供作業執行者(Job Executor)和非同步作業執行者(Async Executor),Async Executor執行表現 ...
  • 前言 之前寫過一篇關於 "JVM記憶體區域劃分" 的文章,但是昨天接到螞蟻金服的面試,問到JVM相關的內容,解釋一下JVM的記憶體區域劃分,這部分答得還不錯,但是後來又問了Java裡面String存放的位置,之前只記得String是一個不變的量,應該是要存放在常量池裡面的,但是後來問到new一個Stri ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...