作者: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边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。

Sobel算子 x方向

(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方向卷积;

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方向卷积运算的实现

//---------------------------------------------------

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;

oDATA <= 0;

endmodule

LineBufferIP设置

MAC_3 IP的设置

PA_3 IP的设置

FPGA基于Sobel算子图像边缘检测的实现结果:

lena原图

7. 引用文档

1--------------------------------------------------------------------- 百度百科

2基于FPGA的Sobel边缘检测的实现--------------------------------NingHeChuan

最后欢迎大家关注我的扣扣群,微信公众号。

axios获取json数据 axios怎么读取json文件

在项目根目录有一个static文件夹目录,将所需要的json文件放在该static目录下,使用axios发起get请求获取对应的json文件数据main.jsimport axios from 'axios' // 安装axios后引入 Vue.prototype.$axios = axios // 将axios挂载到原型上方便使用test.vuethis.$axios.get('/sta

Python的强制转化数据类型 python强制类型转换成string

毫无疑问,Python 是一门强类型语言。强类型语言。强类型语言! 这就意味着,不同类型的对象通常需要先做显式地类型转化, 然后才能进行某些操作。 下面以字符串和数字为例,看看强行操作会产生什么结果:>>> "Python猫" + 666 Traceback (most recent call last): File "<stdin>", line 1, in &

* 件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分。 * 头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序的声明(declaration),而定义文件用于保存程序的实现 (implementation)。 * 为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断上传文件是否符合格式。具体代码如