基于FPGA的图像sobel边缘提取算法开发,包括tb测试文件以及matlab验证代码

76 阅读3分钟

1.算法运行效果图预览

8d730bb53e9775c9784004408438039a_82780907_202311091606520589716057_Expires=1699517812&Signature=Rts5lpqW0z2fp5BFApzRs9YdHFc%3D&domain=8.jpeg

633bdb1557ea91b38cdeb30a0b7a2e25_82780907_202311091606520745366497_Expires=1699517812&Signature=nYGsvkCf13zsBzS1RxgMMGgUXh4%3D&domain=8.jpeg  

2.算法运行软件版本

vivado2019.2

 

matlab2022a

 

 

3.算法理论概述

        图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。有许多方法用于边缘检测,它们的绝大部分可以划分为两类:基于查找一类和基于零穿越的一类。基于查找的方法通过寻找图像一阶导数中的最大和最小值来检测边界,通常是将边界定位在梯度最大的方向。基于零穿越的方法通过寻找图像二阶导数零穿越来寻找边界,通常是Laplacian过零点或者非线性差分表示的过零点。

 

       Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。Soble边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。所以我们先定义两个梯度方向的系数:

 

90dd58e0537bdf759fcb8516e8bfa017_82780907_202311091608110838972802_Expires=1699517891&Signature=U45tpbfDM8OiHLlfjR4m%2FNzCI0Y%3D&domain=8.png  

        然后我们来计算梯度图像,我们知道边缘点其实就是图像中灰度跳变剧烈的点,所以先计算梯度图像,然后将梯度图像中较亮的那一部分提取出来就是简单的边缘部分。

 

        Sobel算子用了一个3*3的滤波器来对图像进行滤波从而得到梯度图像,这里面不再详细描述怎样进行滤波及它们的意义等。

 

竖起方向的滤波器:y_mask=op = [-1 -2 -1;0 0 0;1 2 1]/8;

 

水平方向的滤波器:op的转置:x_mask=op’;

 

定义好滤波器后,我们就开始分别求垂直和竖起方向上的梯度图像。用滤波器与图像进行卷积即可:

 

bx = abs(filter2(x_mask,a));

by = abs(filter2(y_mask,a));

 

上面bx为水平方向上的梯度图像,by为垂直方向上的梯度图像。为了更清楚的说明算法过程,下面给出一张示例图像的梯度图像。

 

 

 

4.部分核心程序 ``timescale 1ns / 1ps

//

// Company:

// Engineer:

//

// Create Date: 2023/07/31

// Design Name:

// Module Name: sobel

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//

 

 

module tops(

input i_clk,

input i_rst,

input[7:0]i_I,

output reg[7:0]o_sobel

);

   

parameter LEN = 256; 

parameter th  = 255;     

 

........................................................

 

 

  

 

reg signed[10:0]x1;

reg signed[10:0]x2;

 

reg signed[10:0]y1;

reg signed[10:0]y2;

 

reg signed[11:0]x12;

reg signed[11:0]y12;

 

reg signed[11:0]x_; 

reg signed[11:0]y_; 

 

reg signed[12:0]edge_; 

 

always @(posedge i_clk or posedge i_rst)

begin

     if(i_rst)

     begin

     x1 <=11'd0;

     x2 <=11'd0;

 

     y1 <=11'd0;

     y2 <=11'd0;

 

     x12<=12'd0;

     y12<=12'd0;

 

     x_<=11'd0;

     y_<=11'd0;

 

     edge_ <=13'd0;

     end

else begin

.........................................................

 

     edge_<= x_ +  y_;  // 计算Sobel算子响应的绝对值和

     end

end

   

   

   

always @(posedge i_clk or posedge i_rst)

begin

     if(i_rst)

     begin

     o_sobel <= 8'd0;

     end

else begin

 

          if(edge_>=th) //判断绝对值和是否大于阈值

          o_sobel <= 8'd255;

          else

          o_sobel <= 8'd0;

 

     end

end 

   

   

endmodule`