边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮
度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。 这些包括(i)
深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。 边缘
检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。
边缘检测算子
一阶: Roberts Cross 算子, Prewitt 算子, Sobel 算子, Kirsch 算子,罗盘算子;
二阶: Marr-Hildreth,在梯度方向的二阶导数过零点, Canny 算子, Laplacian 算子。 今
天我们要讲的是基于 Sobel 算子的边缘检测的 FPGA 算法的实现。

Sobel 算法是像素图像边缘检测中最重要的算子之一,在机器学习、数字媒体、计算机
视觉等信息科技领域起着举足轻重的作用。在技术上,它是一个离散的一阶差分算子,用来
计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应
的梯度矢量或是其法矢量
Sobel 边缘检测算法比较简,实际应用中效率比 canny 边缘检测效率要高,但是边缘不
如 Canny 检测的准确,但是很多实际应用的场合, sobel 边缘却是首选,尤其是对效率要求
较高,而对细纹理不太关心的时候。
Sobel 边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。

实现步骤:
1. Gx = P ★Sobelx – 原始图像与 Sobel 算子 X 方向卷积;
2. Gy = P★Sobely – 原始图像与 Sobel 算子 Y 方向卷积;
3. G = 两个分量的平方和的算数平方根
4. 阈值比较形成边缘查找后的二值图像。

实现代码如下:

/* 
Filename    : Sobel.v
Compiler    : Quartus II 13.0
Description : implement Sobel Edge Detector 
Release     : 
*/

module sobel (
  input            iCLK,
  input            iRST_N,
  input      [7:0] iTHRESHOLD,
  input            iDVAL,
  input      [9:0] iDATA,
  output reg       oDVAL,
  output reg [9:0] oDATA
);

// mask x
parameter X1 = 8'hff, X2 = 8'h00, X3 = 8'h01;
parameter X4 = 8'hfe, X5 = 8'h00, X6 = 8'h02;
parameter X7 = 8'hff, X8 = 8'h00, X9 = 8'h01;

// mask y
parameter Y1 = 8'h01, Y2 = 8'h02, Y3 = 8'h01;
parameter Y4 = 8'h00, Y5 = 8'h00, Y6 = 8'h00;
parameter Y7 = 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;

LineBuffer LineBuffer_inst (
  .clken(iDVAL),
  .clock(iCLK),
  .shiftin(iDATA[9:2]),
  .taps0x(Line0),
  .taps1x(Line1),
  .taps2x(Line2)
);

// 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)
);

// 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 pa0 (
  .clock(iCLK),
  .data0x(Mac_x0),
  .data1x(Mac_x1),
  .data2x(Mac_x2),
  .result(Pa_x)
);

PA_3 pa1 (
  .clock(iCLK),
  .data0x(Mac_y0),
  .data1x(Mac_y1),
  .data2x(Mac_y2),
  .result(Pa_y)
);

SQRT sqrt0 (
  .clk(iCLK),
  .radical(Pa_x * Pa_x + Pa_y * Pa_y),
  .q(Abs_mag)
);

always@(posedge iCLK, 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设置:

深度学习边缘检测lena 边缘检测算法应用_图像处理


深度学习边缘检测lena 边缘检测算法应用_深度学习边缘检测lena_02


深度学习边缘检测lena 边缘检测算法应用_Mac_03


深度学习边缘检测lena 边缘检测算法应用_边缘检测_04