Sobel算子的邊緣檢測實現


轉載於: http://blog.chinaaet.com/crazybingo/p/33388

 

同上一篇,還是為了體現FPGA的強大功能,實現實時的邊緣檢測能力!這一部分簡單的可以用Sobel實現,如果想做的好,可以用高斯+Canny來實現,總是,只要你想做,FPGA沒有什么做不到的,只要你靜得下心來!!!!以下僅僅介紹Soebl算法的Matlab算法實現,希望大家各自努力!

 

1. Sobel算子的邊緣檢測實現

1.1. 邊緣檢測概念

所謂邊緣是指其周圍像素灰度急劇變化的那些象素的集合,它是圖像最基本的特征。邊緣存在於目標、背景和區域之間,所以,它是圖像分割所依賴的最重要的依據。由於邊緣是位置的標志,對灰度的變化不敏感,,因此,邊緣也是圖像匹配的重要的特征。

邊緣檢測和區域划分是圖像分割的兩種不同的方法,二者具有相互補充的特點。在邊緣檢測中,是提取圖像中不連續部分的特征,根據閉合的邊緣確定區域。而在區 域划分中,是把圖像分割成特征相同的區域,區域之間的邊界就是邊緣。由於邊緣檢測方法不需要將圖像逐個像素地分割,因此更適合大圖像的分割。 
邊緣大致可以分為兩種,一種是階躍狀邊緣,邊緣兩邊像素的灰度值明顯不同;另一種為屋頂狀邊緣,邊緣處於灰度值由小到大再到小的變化轉折點處。 
邊緣檢測的主要工具是邊緣檢測模板。

邊緣檢測的有很多,典型的有索貝爾算子,普里維特算子,羅伯茨交叉邊緣檢測等邊緣檢測技術,在Matlab中有現成的IPT函數,提供邊緣檢測,如下,Sobel邊緣檢測:

IMG1 = imread('D:\Matlab_Project\BMP\Lenna.jpg');    % 讀取RGB文件,Lanna PlayBoy

subplot(1,3,1)

imshow(IMG1);

title('原圖像');

IMG1 = rgb2gray(IMG1);

[m,n] = size(IMG1); %用Sobel微分算子進行邊緣檢測

IMG2 = edge(IMG1,'sobel');

subplot(1,3,2);

imshow(IMG2);

title('Sobel邊緣檢測得到的圖像');

wps_clip_image-23339

但效果不佳,靈活性也不高。此處我主要介紹Sobel算子的使用:

1.2. Sobel算法實現

1.2.1. Sobel算法分析

索貝爾算子(Sobel operator)主要用作邊緣檢測,在技術上,它是一離散性差分算子,用來運算圖像亮度函數的灰度之近似值。在圖像的任何一點使用此算子,將會產生對應的灰度矢量或是其法矢量。

Sobel卷積因子為:

wps_clip_image-4145

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

wps_clip_image-4687

圖像的每一個像素的橫向及縱向灰度值通過以下公式結合,來計算該點灰度的大小:

wps_clip_image-11991

通常,為了提高效率 使用不開平方的近似值,但這樣做會損失精度

wps_clip_image-7494

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

        if(temp3 > THRESHOLD)

            IMG_Sobel(i,j) = 0;     %Black

        else

            IMG_Sobel(i,j) = 255;   %White

        end

然后可用以下公式計算梯度方向(當然只要檢測邊緣,則不用計算方向):

wps_clip_image-16343

1.2.2. Sobel算子Matlab算法的實現

Sobel算子根據像素點上下、左右鄰點灰度加權差,在邊緣處達到極值這一現象檢測邊緣。對噪聲具有平滑作用,提供較為精確的邊緣方向信息,邊緣定位精度不夠高。當對精度要求不是很高時,是一種較為常用的邊緣檢測方法。 
Soble算子操作的是灰度圖像,因此必須首先對圖像進行灰度化。這一部分在第一章中詳細介紹過,不再做具體分析,一下算法直接應用灰度圖像。

(1)Sobel算子卷積

% -----------------------------------------------------------------------

%         Gx                  Gy                  Pixel

% [   -1  0   +1  ]   [   +1  +2   +1 ]     [   P1  P2   P3 ]

% [   -2  0   +2  ]   [   0   0    0  ]     [   P4  P5   P6 ]

% [   -1  0   +1  ]   [   -1  -2   -1 ]     [   P7  P8   P9 ]

Sobel_X = [-1, 0, 1, -2, 0, 2, -1, 0, 1];   % Mask x

Sobel_Y = [1, 2, 1, 0, 0, 0, -1, -2, -1];   % Mask y

(2)點對點卷積運算實現梯度的計算

IMG_Gray = double(IMG2);    %將圖片轉換為雙精度類型

IMG_Sobel = true(h,w);     %新建一個二值矩陣

THRESHOLD =90;

for i = 2 : h-1     %舍棄了邊緣信息

    for j = 2 : w-1

        temp1 = Sobel_X(1) * IMG_Gray(i-1,j-1)  + Sobel_X(2) * IMG_Gray(i-1,j)  + Sobel_X(3) * IMG_Gray(i-1,j+1) +...

                Sobel_X(4) * IMG_Gray(i,j-1)    + Sobel_X(5) * IMG_Gray(i,j)    + Sobel_X(6) * IMG_Gray(i,j+1) +...

                Sobel_X(7) * IMG_Gray(i+1,j-1)  + Sobel_X(8) * IMG_Gray(i+1,j)  + Sobel_X(9) * IMG_Gray(i+1,j+1);

        temp2 = Sobel_Y(1) * IMG_Gray(i-1,j-1)  + Sobel_Y(2) * IMG_Gray(i-1,j)  + Sobel_Y(3) * IMG_Gray(i-1,j+1) +...

                Sobel_Y(4) * IMG_Gray(i,j-1)    + Sobel_Y(5) * IMG_Gray(i,j)    + Sobel_Y(6) * IMG_Gray(i,j+1) +...

                Sobel_Y(7) * IMG_Gray(i+1,j-1)  + Sobel_Y(8) * IMG_Gray(i+1,j)  + Sobel_Y(9) * IMG_Gray(i+1,j+1);

        temp3 = sqrt(temp1^2 + temp2^2);

        %temp3 = abs(temp1) + abs(temp2);   %just for speed

        if(temp3 > THRESHOLD)

            IMG_Sobel(i,j) = 0; %Black

        else

            IMG_Sobel(i,j) = 1; %White

        end

    end

end

(3)THRESHOLD為手動設定,此處為90。根據圖像的質量來調節,針對於邊緣檢測而言,不需要進行梯度方向計算,因此直接進行梯度計算,與閥值對比,既可以實現邊緣檢測。

1.2.3. 效果圖

THRESHOLD = 90下的圖像

wps_clip_image-8377

 

 

 

 

 

最后曬個圖吧,呵呵FPGA移植的,絕對不是抄襲 “無雙OO”,他那個寫的實在是太惡心了(無意冒犯前輩,不好意思)。。。。。。

實際上簡化后的算法如下:

 

//---------------------------------------
//Caculate vertical Grade with |abs|
reg	[9:0]	Gy_temp1;	//postive result
reg	[9:0]	Gy_temp2;	//negetive result
reg	[9:0]	Gy_data;	//Vertical grade data
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		Gy_temp1 <= 0;
		Gy_temp2 <= 0;
		Gy_data <= 0;
		end
	else
		begin
		Gy_temp1 <= image_p11 + (image_p12 << 1) + image_p13;	//postive result
		Gy_temp2 <= image_p31 + (image_p32 << 1) + image_p33;	//negetive result
		Gy_data <= (Gy_temp1 >= Gy_temp2) ? Gy_temp1 - Gy_temp2 : Gy_temp2 - Gy_temp1;
		end
end

//---------------------------------------
//Caculate the square of distance = (Gx^2 + Gy^2)
reg	[20:0]	Gxy_square;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		Gxy_square <= 0;
	else
		Gxy_square <= Gx_data * Gx_data + Gy_data * Gy_data;
end

//---------------------------------------
//Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5
wire	[10:0]	Dim;
SQRT	u_SQRT
(
	.radical	(Gxy_square),
	.q			(Dim),
	.remainder	()
);

 

03_VIP_Gray_Sobel


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM