FPGA图像处理之边缘检测算法的实现
作者:lee神
1. 背景知识
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。这些包括(i)深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。
2. 边缘检测算子
一阶:Roberts Cross算子,Prewitt算子,Sobel算子,Kirsch算子,罗盘算子;二阶:Marr-Hildreth,在梯度方向的二阶导数过零点,Canny算子,Laplacian算子。今天我们要讲的是基于Sobel算子的边缘检测的FPGA算法的实现。
3. Sobel算子实现
Sobel算法是像素图像边缘检测中最重要的算子之一,在机器学习、数字媒体、计算机视觉等信息科技领域起着举足轻重的作用。在技术上,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量
Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。
Soble边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。
-1 |
0 |
+1 |
-2 |
0 |
+2 |
-1 |
0 |
+1 |
Sobel算子 x方向
+1 |
+2 |
+1 |
0 |
0 |
0 |
-1 |
-2 |
-1 |
Y方向
(i-1,j-1) |
( i,j-1) |
(i+1,j-1) |
(i-1,j) |
(i,j) |
(i+1,j) |
(i-1,j+1) |
(i,j+1) |
(i+1,j+1) |
原始图像P
实现步骤:
1.Gx = P ★Sobelx -- 原始图像与Sobel算子X方向卷积;
2. Gy= P★Sobely -- 原始图像与Sobel算子Y方向卷积;
3.
。
4. 阈值比较形成边缘查找后的二值图像。
4. C语言实现
/* Sobel template
a00 a01 a02
a10 a11 a12
a20 a21 a22
*/
unsigned char a00, a01, a02;
unsigned char a10, a11, a12;
unsigned char a20, a21, a22;
void MySobel(IplImage* gray, IplImage* gradient)
{
CvScalar color ;
for (int i=1; i<gray->height-1; ++i)
{
for (int j=1; j<gray->width-1; ++j)
{
a00 = cvGet2D(gray, i-1, j-1).val[0];
a01 = cvGet2D(gray, i-1, j).val[0];
a02 = cvGet2D(gray, i-1, j+1).val[0];
a10 = cvGet2D(gray, i, j-1).val[0];
a11 = cvGet2D(gray, i, j).val[0];
a12 = cvGet2D(gray, i, j+1).val[0];
a20 = cvGet2D(gray, i+1, j-1).val[0];
a21 = cvGet2D(gray, i+1, j).val[0];
a22 = cvGet2D(gray, i+1, j+1).val[0];
// x方向上的近似导数 卷积运算
double ux = a20 * (1) + a10 * (2) + a00 * (1)
+ (a02 * (-1) + a12 * (-2) + a22 * (-1));
// y方向上的近似导数 卷积运算
double uy = a02 * (1) + a01 * (2) + a00 * (1)
+ a20 * (-1) + a21 * (-2) + a22 * (-1);
color.val[0] = sqrt(ux*ux + uy*uy);
cvSet2D(gradient, i, j, color);
}
}
}
//注释:该程序需要在安装Opencv软件下运行。
5. Matlab边缘检测的实现
ps=imread('lena.jpg'); %读取图像
subplot(1,3,1)
imshow(ps);
title('原图像');
ps=rgb2gray(ps);
[m,n]=size(ps); %用Sobel微分算子进行边缘检测
pa = edge(ps,'sobel');
subplot(1,3,2);
imshow(pa);
title('Sobel边缘检测得到的图像');
结果:
效果图
6. FPGA实现
硬件平台:小梅哥AC620开发板,4.3英寸TFT显示屏
软件:Quartus 13.0
我将在FPGA程序中注释,表示实现过程。我们使用的图像为480x272。
/*
Filename : Sobel.v
Compiler : Quartus II 13.0
Description: implement Sobel Edge Detector
Release :
*/
modulesobel (
input iCLK,
input iRST_N,
input [7:0] iTHRESHOLD,
input iDVAL,
input [9:0] iDATA,
output reg oDVAL,
output reg [9:0] oDATA
);
//----------------------------------------------------
// 将Sobel算子换算成有符号数(signed)
//----------------------------------------------------
// maskx
parameterX1 = 8'hff, X2 = 8'h00, X3 = 8'h01;
parameterX4 = 8'hfe, X5 = 8'h00, X6 = 8'h02;
parameterX7 = 8'hff, X8 = 8'h00, X9 = 8'h01;
// masky
parameterY1 = 8'h01, Y2 = 8'h02, Y3 = 8'h01;
parameterY4 = 8'h00, Y5 = 8'h00, Y6 = 8'h00;
parameterY7 = 8'hff, Y8 = 8'hfe, Y9 = 8'hff;
wire [7:0] Line0;
wire [7:0] Line1;
wire [7:0] Line2;
wire [17:0] Mac_x0;
wire [17:0] Mac_x1;
wire [17:0] Mac_x2;
wire [17:0] Mac_y0;
wire [17:0] Mac_y1;
wire [17:0] Mac_y2;
wire [19:0] Pa_x;
wire [19:0] Pa_y;
wire [15:0] Abs_mag;
//---------------------------------------------
// 实现3x3矩阵原始图像 P
//---------------------------------------------
LineBufferLineBuffer_inst (
.clken(iDVAL),
.clock(iCLK),
.shiftin(iDATA[9:2]),
.taps0x(Line0),
.taps1x(Line1),
.taps2x(Line2)
);
//--------------------------------------------
// Gx = P★Sobelx
// x方向卷积运算实现
//---------------------------------------------
MAC_3 x0(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line0),
.datab_0(X9),
.datab_1(X8),
.datab_2(X7),
.result(Mac_x0)
);
MAC_3 x1(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line1),
.datab_0(X6),
.datab_1(X5),
.datab_2(X4),
.result(Mac_x1)
);
MAC_3 x2(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line2),
.datab_0(X3),
.datab_1(X2),
.datab_2(X1),
.result(Mac_x2)
);
PA_3 pa0(
.clock(iCLK),
.data0x(Mac_x0),
.data1x(Mac_x1),
.data2x(Mac_x2),
.result(Pa_x)
);
//---------------------------------------------------
// Gy =P★Sobely
// y方向卷积运算的实现
//---------------------------------------------------
// Y
MAC_3 y0(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line0),
.datab_0(Y9),
.datab_1(Y8),
.datab_2(Y7),
.result(Mac_y0)
);
MAC_3 y1(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line1),
.datab_0(Y6),
.datab_1(Y5),
.datab_2(Y4),
.result(Mac_y1)
);
MAC_3 y2(
.aclr3(!iRST_N),
.clock0(iCLK),
.dataa_0(Line2),
.datab_0(Y3),
.datab_1(Y2),
.datab_2(Y1),
.result(Mac_y2)
);
PA_3 pa1(
.clock(iCLK),
.data0x(Mac_y0),
.data1x(Mac_y1),
.data2x(Mac_y2),
.result(Pa_y)
);
//-----------------------------------------------
// 得到G
//-----------------------------------------------
SQRTsqrt0 (
.clk(iCLK),
.radical(Pa_x * Pa_x + Pa_y * Pa_y),
.q(Abs_mag)
);
//-------------------------------------------------
// 阈值比较
//-------------------------------------------------
always@(posedgeiCLK, negedge iRST_N) begin
if (!iRST_N)
oDVAL<= 0;
else begin
oDVAL <= iDVAL;
if (iDVAL)
oDATA <= (Abs_mag > iTHRESHOLD) ? 0: 1023;
else
oDATA <= 0;
end
end
endmodule
IP设置
LineBufferIP设置
MAC_3 IP的设置
PA_3 IP的设置
FPGA基于Sobel算子图像边缘检测的实现结果:
lena原图
阈值3
阈值5
阈值7
7. 引用文档
1---------------------------------------------------------------------百度百科
2基于FPGA的Sobel边缘检测的实现--------------------------------NingHeChuan最后欢迎大家关注我的扣扣群,微信公众号。