1. 程式人生 > >基於FPGA的影象邊緣檢測

基於FPGA的影象邊緣檢測

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

目錄
mif檔案的製作
呼叫 ip 核生成rom以及在 questasim 模擬注意問題
灰度處理
均值濾波:重點是3*3 畫素陣列的生成
sobel邊緣檢測
圖片的顯示
結果展示
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;
複製程式碼

灰度處理
任何顏色都由紅、綠、藍三原色組成,假如原來某點的顏色為( 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
複製程式碼

均值濾波
均值濾波的原理

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

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

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

下面這個圖是我自己畫的 FPGA 如何將矩陣資料處理成並行的畫素點,可以結合下面的程式碼好好理解,這也是精華所在。

正方形紅框框起來的是第一個完整的 3*3 矩陣,長方形紅框框起來的是並行的畫素點,在此基礎上就可以求得平均值,進行均值濾波。

從下圖也能看到 3*3 矩陣從左往右滑動。

第一個3*3 陣列。

0 1 2 – > p11 p12 p13

3 4 5 – > p21 p22 p23

6 7 8 – > p31 p32 p33

核心程式碼如下:

複製程式碼
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      

複製程式碼

網頁的介面如下,將引數設定好以後就可以顯示圖片。

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

結果展示

1 原圖

2 灰度圖

3 均值濾波

4 邊緣檢測 閾值為5

5 閾值為 10

6 閾值為 16

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

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

                                                                                                                                                                                   aslmer

相關推薦

基於FPGA影象邊緣檢測

本文主要內容是實現影象的邊緣檢測功能 目錄 mif檔案的製作 呼叫 ip 核生成rom以及在 questasim 模擬注意問題 灰度處理 均值濾波:重點是3*3 畫素陣列的生成 sobel邊緣檢測 圖片的顯示 結果展示 mif檔案的製作 受資

【OpenCV影象處理入門學習教程四】基於LoG運算元的影象邊緣檢測

一、基於LoG運算元的影象邊緣檢測原圖:1.LoG運算元與自定義濾波運算元進行比較的結果:2.LoG運算元的結果:3.自定義3*31 1 1 1 -8 1 1 1 1 濾波結果:二、程式碼解析下面是一段基於LoG運算元的影象邊緣檢測的程式碼,同時會生成兩個結果,一個是LoG運算元的結果,第二個是自

基於FPGA的頻率檢測與LCD顯示

大於 等精度測頻 pll info 技術 進制 測試 方案 mod 基於FPGA的信號測頻器說明文檔 設計要求 利用FPGA設計一個信號測頻器,要求: (1)測量脈沖信號; (2)頻率測量1-10MHz以及占空比10%-99% 精確到1%; (3)將測出頻率和占空比顯示在L

影象處理】RGB影象邊緣檢測

灰度圖邊緣檢測    在學習影象處理時,首先接觸到的就是灰度影象的邊緣檢測,這是影象處理最基礎的也是最重要的一環,熟悉影象邊緣檢測有助於我們學習其他的數字影象處理方法。由於影象的邊緣區域會存在明顯的畫素值階躍,因此邊緣檢測主要是通過獲得影象灰度梯度,進而通過梯

影象邊緣檢測——幾種影象邊緣檢測運算元的學習及python 實現

  本文學習利用python學習邊緣檢測的濾波器,首先讀入的圖片程式碼如下: import cv2 from pylab import * saber = cv2.imread("construction.jpg") saber = cv2.cvtColor(saber,cv2.COLOR_BGR2RG

影象邊緣檢測、角點特徵檢測以及SURF特徵提取

1.影象的邊緣檢測 影象的邊緣是指其周圍畫素灰度急劇變化的那些畫素的集合。邊緣檢測的基本思想是先檢測影象中的邊緣點,在按照某種策略將邊緣點連線成輪廓,從而構成分割區域。 利用edge對輸入的灰度影象進行邊緣檢測 I=imread(‘circuit

影象邊緣檢測—sobel運算元(灰度影象,彩色影象

void CShowPicView::Ontwodimension() { CShowPicDoc* pDoc = GetDocument(); CDC* pDC=GetDC(); // 字串 CString str; int x,y; int i,n; x=intHeight; y=int

影象邊緣檢測-運算元比較總結

一階導數運算元   1, Roberts運算元:對具有陡峭的低噪聲的影象處理效果較好。形式如下: [100−1] [

openCV—Python(11)—— 影象邊緣檢測

一、函式簡介 1、laplacian運算元 函式原型:Laplacian(src, ddepth, dst=None, ksize=None, scale=None, delta=None, borderType=None) src:影象矩陣 dde

第六節--基於Sobel的邊緣檢測C++程式的實現

 /********************************************************************************************************** *函式原型:BOOL CImgProcess::Ed

影象邊緣檢測經典運算元及MATLAB實現

一、邊緣檢測 邊緣是圖象最基本的特徵. 邊緣檢測在計算機視覺、圖象分析等應用中起著重要的作用,是圖象分析與識別的重要環節,這是因為子圖象的邊緣包含了用於識別的有用資訊. 所以邊緣檢測是影象分析和模式識別的主要特徵提取手段。所謂邊緣是指其周圍畫素灰度後階變化或屋頂狀變化的

影象邊緣檢測邊緣增強處理——(Roberts、prewitt、sobel)

堅持寫下去,雖然簡單,但希望可以幫助到別人,有不足之處還望指教目的:對影象採用3種邊緣檢測運算元進行處理,比較處理後的結果,並用邊緣增強演算法對影象增強。一、基本原理1.1影象邊緣   影象邊緣是影象最基本的特徵之一,往往攜帶著一幅影象的大部分資訊。而邊緣存在於影象的不規則結

我的CUDA學習之旅4——Sobel運算元影象邊緣檢測CUDA實現

引言 關於影象邊緣檢測,記得剛開始接觸影象處理時,第一個自己實現的程式是通過筆記本攝像頭採集影象,利用OpenCV自帶的演算法庫進行Canny運算元邊緣檢測,那時候當看到程式執行後,視訊視窗實時顯示經Canny運算元邊緣分割後的影象,覺得十分有科技感,後來慢慢

OpenCV影象邊緣檢測(Laplace演算法)

一、Laplace演算法簡介   二階微分在亮的一邊是負的,在暗的一邊是正的。常數部分為零。可以用來確定邊的準確位置,以及畫素在亮的一側還是暗的一側。   拉普拉斯運算元是最簡單的各向同性微分運算元,具有旋轉不變性。一個二維影象函式 的拉普拉斯變換是各向同性

android studio 使用 jni 編譯 opencv 完整例項 之 影象邊緣檢測!從此在andrid中自由使用 影象匹配、識別、檢測

1 package io.github.froger.jni; 2 3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.drawable.BitmapDra

降噪 (Noise Reduction)對於影象邊緣檢測 (Edge Detection)的意義

對於拍攝到的影象,在識別其中物體的邊緣時,一定要先降噪 1. 首先,邊緣檢測的演算法如下圖所示: 原始影象如上圖所示,肉眼可見清晰的邊緣。 其強度函式 (Intensity Function)如下: 那麼,邊緣的識別是基於強度函式的一

openCV實現影象邊緣檢測

最近自己在做一個有關影象處理的小專案,涉及到影象的邊緣檢測、直線檢測、輪廓檢測以及角點檢測等,本文首先介紹影象的邊緣檢測,使用的是Canny邊緣檢測演算法,具體程式碼以及檢測效果如下: 1、程式碼部分: // Image_Canny.cpp : 定義控制檯應用程式的入口點

opencv影象邊緣檢測

邊緣檢測檢測 &&邊緣檢測可以提取影象重要輪廓資訊,減少影象內容,可以用於分割影象,做特徵 提取 &&邊緣檢測的一般步驟 濾波——(濾出噪聲對檢測邊緣的影響) 濾高頻 增強——(可以將畫素鄰域強度變化凸顯出來–梯度運算元)

影象邊緣檢測——canny運算元原理與程式碼

轉自:http://blog.csdn.net/dcrmg/article/details/5234490 另有:http://blog.csdn.net/likezhaobin/article/details/6892629             http:/

【OpenCV影象處理】二十二、影象邊緣檢測(上)

→影象邊緣檢測的目的是檢測鄰域內灰度明顯變化的畫素,常用一階差分和二階差分來進行邊緣檢測 →數字影象中的邊緣是由鄰域內灰度值明顯變化的畫素構成,邊緣檢測主要是影象灰度的度量檢測和定位 →影象的邊緣有方向和幅值兩個屬性,沿邊緣方向畫素灰度值變化平緩或不發生變化,而垂直於邊緣方