基於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的值越大,顏色越接近白色,反之越接近黑色(這是我自己的理解,不嚴謹錯誤之處請大神指正)。
這是線上調色盤網址,可以進去自己研究一下。
此次我採用是浮點演算法來實現灰度圖的,我的圖片資料是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影象處理】二十二、影象邊緣檢測(上)
→影象邊緣檢測的目的是檢測鄰域內灰度明顯變化的畫素,常用一階差分和二階差分來進行邊緣檢測 →數字影象中的邊緣是由鄰域內灰度值明顯變化的畫素構成,邊緣檢測主要是影象灰度的度量檢測和定位 →影象的邊緣有方向和幅值兩個屬性,沿邊緣方向畫素灰度值變化平緩或不發生變化,而垂直於邊緣方