0%

FPGA图像处理之常用图像锐化算法

本节主要介绍了FPGA图像处理中常用的图像锐化算法,包括Robert锐化算法、Sobel锐化算法、Laplacian锐化算法,以及它们的MATLAB与FPGA实现。

图像锐化的基本概念

  • 在增强图像之前一般会先对图像进行平滑处理以减少或消除噪声, 图像的能量主要集中在低频部分, 而噪声和图像边缘信息的能量主要集中在高频部分。
  • 因此, 平滑处理会使原始图像的边缘和轮廓变得模糊。
  • 为了减少不利效果的影响, 需要利用图像锐化技术, 使图像的边缘变得清晰
  • 图像锐化处理主要有两个目的:
    • 一是与图像平滑处理相反, 增强图像边缘, 使模糊的图像更加清晰, 颜色变得鲜明突出, 图像的质量有所改善, 产生更适合人观察和识别的图像;
    • 二是经过图像锐化处理后, 目标物体的边缘鲜明, 便于计算机提取目标物体的边界、 对图像进行分割、 识别目标区域等,为理解和分析图像打下基础。
  • 经过平滑处理的图像变得模糊的根本原因是图像进行了平均或积分运算, 因此可以对其进行逆运算(如微分运算) , 从而可以使图像变得清晰。 微分运算是求信号的变化率, 由傅里叶变换的微分性质可知, 微分运算具有加强高频分量的作用。
  • 图像在进行锐化处理时必须有较高的信噪比, 否则,锐化后图像的信噪比反而更低,从而凸显了图像的噪声而没有锐化边缘,因此,一般是先消除或减少噪声后再进行图像锐化处理

Robert锐化算法

  • Robert算子是一种利用局部差分寻找边缘算子的方法, 即计算对角方向相邻的两个像素之差。 利用Robert算子可以计算两个对角方向的梯度 $G_x$和$G_y$
    $$
    G_x = \begin{bmatrix}
    1 & 0 \
    0 & -1 \
    \end{bmatrix}\times \begin{bmatrix}
    I_{11} & I_{12} \
    I_{21} & I_{22} \
    \end{bmatrix}\quad
    G_x = \begin{bmatrix}
    0 & 1 \
    -1 & 0 \
    \end{bmatrix}\times \begin{bmatrix}
    I_{11} & I_{12} \
    I_{21} & I_{22} \
    \end{bmatrix}\quad
    $$

  • 将两个对角方向的梯度$G_x$和$G_y$合并后取模得到最终的梯度$G$
    $$
    G = \sqrt{G_x^2 + G_y^2}=\sqrt{(I_{11}-I_{22})^2+(I_{12}-I_{21})^2}
    $$

  • $G$表示处理后的梯度,作为边缘检测的结果,该结果加上原图,即为锐化结果

1.Robert锐化的MATLAB实现

  • Robert_Edge_Detector.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    % 灰度图像Robert边缘检测算法实现
    % IMG为输入的灰度图像
    % Q为输出的灰度图像
    function Q = Robert_Edge_Detector(IMG)

    [h,w] = size(IMG); % 获取图像的高度h和宽度w
    Q = zeros(h,w); % 初始化Q为全0的h*w大小的图像

    % -------------------------------------------------------------------------
    % Wx Wy Pixel
    % [ 0 +1 ] [ +1 0 ] [ P1 P2 ]
    % [ -1 0 ] [ 0 -1 ] [ P3 P4 ]
    Wx = [0,1;-1,0]; % Weight x
    Wy = [1,0;0,-1]; % Weight y

    IMG = double(IMG);

    for i = 1 : h
    for j = 1 : w
    if(i>h-1 || j>w-1)
    Q(i,j) = 0; % 图像右边缘和下边缘像素不处理
    else
    Gx = Wx(1,1)*IMG(i ,j) + Wx(1,2)*IMG(i ,j+1) +...
    Wx(2,1)*IMG(i+1,j) + Wx(2,2)*IMG(i+1,j+1);
    Gy = Wy(1,1)*IMG(i ,j) + Wy(1,2)*IMG(i ,j+1) +...
    Wy(2,1)*IMG(i+1,j) + Wy(2,2)*IMG(i+1,j+1);
    Q(i,j) = sqrt(Gx^2 + Gy^2);
    end
    end
    end
    Q=uint8(Q);
  • 首先获取以目标像素为顶点的2×2窗口, 分别与两个对角方向的Robert算子做卷积运算, 得到两个方向的梯度Gx和Gy; 然后将梯度Gx和Gy合并取模得到最终的梯度Q, 即Robert边缘检测的结果; 最后, 如果目标像素位于图像的右边界或下边界,则直接输出0作为Robert边缘检测的结果。

  • Robert_Sharpen_Test.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    clear all; close all; clc;

    % -------------------------------------------------------------------------
    % Read PC image to Matlab
    IMG1 = imread('../../0_images/Lenna.jpg'); % 读取jpg图像
    IMG1 = rgb2gray(IMG1);
    h = size(IMG1,1); % 读取图像高度
    w = size(IMG1,2); % 读取图像宽度
    subplot(131);imshow(IMG1);title('【1】原图');

    % -------------------------------------------------------------------------
    IMG2 = Robert_Edge_Detector(IMG1);
    subplot(132);imshow(IMG2);title('【2】Robert边缘检测结果');

    % -------------------------------------------------------------------------
    IMG3 = IMG1 + IMG2;
    subplot(133);imshow(IMG3);title('【3】Robert锐化图像');
  • 将Robert边缘检测结果与原始图像叠加得到Robert锐化的图像

    image-20241128103145651

2.Robert锐化的FPGA实现

  • 为了能够复用之前的$3\times 3$窗口生成模块,需从$3\times 3$窗口中获取$2\times 2$窗口

    image-20241128150722906
  • 获取$2\times 2$窗口后,就可以开始进行Robert锐化处理了。Robert锐化处理分为以下几步

    1. 分别计算两个对角方向的梯度$Gx_data$和$Gy_data$
      $$
      Gx_data = \begin{bmatrix}
      matrix_p22 & matrix_p23 \
      matrix_p32 & matrix_p33 \
      \end{bmatrix}\times \begin{bmatrix}
      0 & 1 \
      -1 & 0 \
      \end{bmatrix} = matrix_p23 - matrix_p32\
      Gy_data = \begin{bmatrix}
      matrix_p22 & matrix_p23 \
      matrix_p32 & matrix_p33 \
      \end{bmatrix}\times \begin{bmatrix}
      1 & 0 \
      0 & -1 \
      \end{bmatrix} = matrix_p22 - matrix_p33
      $$

    2. 将两个对角方向的梯度$Gx_data$和$Gy_data$合并取模得到最终的梯度$G_data$,即Robert边缘检测结果
      $$
      G_data = \sqrt{(Gx_data)^2+(Gy_data)^2}
      $$

    3. 将梯度$G_data$与原始图像相加得到Robert锐化图像

    4. 还需判断$2\times 2$窗口左上角像素是否位于图像边界,如果位于图像边界,则用$2\times 2$窗口左上角的像素作为Robert锐化结果

    5. Robert锐化图像的灰度值可能大于255,为了防止数据溢出,如果灰度值大于255,则令其等于255

    image-20241128152142268
  • 仿真结果:

    image-20241128154441688


Sobel锐化算法

  • Robert算子只采用梯度微分锐化图像, 会让噪声、 条纹得到增强, 而Sobel算子在一定程度上解决了这个问题, 它是一种先求平均, 再求微分, 最后求梯度的算子。

  • 像素平均相当于对图像进行低通滤波,对噪声相对不敏感,具有抑制噪声的作用。 但Sobel算子对边缘的定位不如Robert算子。

  • 3×3窗口的Sobel边缘检测2个方向的算子( I 为原图) :
    $$
    G_x = \begin{bmatrix}
    -1 & 0 & 1\
    -2 & 0 & 2\
    -1 & 0 & 1\
    \end{bmatrix}\times I\quad
    G_y = \begin{bmatrix}
    -1 & -2 & -1\
    0 & 0 &0\
    1 & 2 & 1\
    \end{bmatrix}\times I
    \
    G = \sqrt{G_x^2 + G_y^2}
    $$

    • 其中的$\times$代表点乘后再相加
  • $G$表示处理后的梯度,作为边缘检测的结果,该结果加上原图,即为锐化结果

1.Sobel锐化的MATLAB实现

  • Sobel_Edge_Detector.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    % 灰度图像Sobel边缘检测算法实现
    % IMG为输入的灰度图像
    % Q为输出的灰度图像
    function Q = Sobel_Edge_Detector(IMG)

    [h,w] = size(IMG); % 获取图像的高度h和宽度w
    Q = zeros(h,w); % 初始化Q为全0的h*w大小的图像

    % -------------------------------------------------------------------------
    % Wx Wy 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]
    Wx = [-1,0,1;-2,0,2;-1,0,1]; % Weight x
    Wy = [-1,-2,-1;0,0,0;1,2,1]; % Weight y

    IMG = double(IMG);

    for i = 1 : h
    for j = 1 : w
    if(i<2 || i>h-1 || j<2 || j>w-1)
    Q(i,j) = 0; % 边缘像素不处理
    else
    Gx = Wx(1,1)*IMG(i-1,j-1) + Wx(1,2)*IMG(i-1,j) + Wx(1,3)*IMG(i-1,j+1) +...
    Wx(2,1)*IMG(i ,j-1) + Wx(2,2)*IMG(i ,j) + Wx(2,3)*IMG(i ,j+1) +...
    Wx(3,1)*IMG(i+1,j-1) + Wx(3,2)*IMG(i+1,j) + Wx(3,3)*IMG(i+1,j+1);
    Gy = Wy(1,1)*IMG(i-1,j-1) + Wy(1,2)*IMG(i-1,j) + Wy(1,3)*IMG(i-1,j+1) +...
    Wy(2,1)*IMG(i ,j-1) + Wy(2,2)*IMG(i ,j) + Wy(2,3)*IMG(i ,j+1) +...
    Wy(3,1)*IMG(i+1,j-1) + Wy(3,2)*IMG(i+1,j) + Wy(3,3)*IMG(i+1,j+1);
    Q(i,j) = sqrt(Gx^2 + Gy^2);
    end
    end
    end
    Q=uint8(Q);
  • Sobel_Sharpen_Test.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    clear all; close all; clc;

    % -------------------------------------------------------------------------
    % Read PC image to Matlab
    IMG1 = imread('../../0_images/Lenna.jpg'); % 读取jpg图像
    IMG1 = rgb2gray(IMG1);
    h = size(IMG1,1); % 读取图像高度
    w = size(IMG1,2); % 读取图像宽度
    subplot(131);imshow(IMG1);title('【1】原图');

    % -------------------------------------------------------------------------
    IMG2 = Sobel_Edge_Detector(IMG1);
    subplot(132);imshow(IMG2);title('【2】Sobel边缘检测结果');

    % -------------------------------------------------------------------------
    IMG3 = IMG1 + IMG2;
    subplot(133);imshow(IMG3);title('【3】Sobel锐化图像');
  • 调用Sobel边缘检测函数, 将Sobel边缘检测结果与原始图像叠加得到Sobel锐化的图像

    image-20241128174044864

  • 可以看出Sobel算子对边缘有较强的响应,与Robert算子相比,对边缘的响应更加强烈,得到的边缘比较粗,但边缘定位精度不够高

2.Sobel锐化的FPGA实现

  • Sobel锐化处理分为以下几步:

    1. 分别计算水平方向梯度$Gx_data$和垂直方向梯度$Gy_data$

      image-20241128174706327
    2. 将水平方向梯度$Gx_data$和垂直方向梯度$Gy_data$合并取模得到最终的梯度$G_data$,即Sobel边缘检测的结果
      $$
      G_data = \sqrt{Gx_data^2 + Gy_data^2}
      $$

    3. 将梯度$G_data$与原始图像叠加得到Sobel锐化的图像

    4. 还需判断$3\times 3$窗口的中心像素是否位于图像边界,如果位于图像边界,则用$3\times 3$窗口的中心像素作为Sobel锐化的结果

    5. Sobel锐化图像的灰度值可能大于255,为了防止数据溢出,如果灰度值大于255,则令其等于255

    image-20241128175137606
  • 仿真结果:

    image-20241128175844001


Laplacian锐化算法

  • Laplacian算子是各向同性、 具有旋转不变性的微分算子, 满足不同走向的图像边缘的锐化要求。

  • 如果将Laplacian算子写成模板形式,通过将图像与模板进行卷积运算可获得图像边缘的检测结果。

    image-20241128193523457

1.Laplacian锐化的MATLAB实现

  • Laplacian_Edge_Detector.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    % 灰度图像Laplacian边缘检测算法实现
    % IMG为输入的灰度图像
    % Q为输出的灰度图像
    function Q = Laplacian_Edge_Detector(IMG)

    [h,w] = size(IMG); % 获取图像的高度h和宽度w
    Q = zeros(h,w); % 初始化Q为全0的h*w大小的图像

    % -------------------------------------------------------------------------
    % W Pixel
    % [ 0 -1 0 ] [ P1 P2 P3]
    % [ -1 4 -1 ] [ P4 P5 P6]
    % [ 0 +1 0 ] [ P7 P8 P9]
    W = [0,-1,0;-1,4,-1;0,-1,0]; % Weight
    % W = [-1,-1,-1;-1,8,-1;-1,-1,-1]; % Weight

    IMG = double(IMG);

    for i = 1 : h
    for j = 1 : w
    if(i<2 || i>h-1 || j<2 || j>w-1)
    Q(i,j) = 0; % 边缘像素不处理
    else
    Q(i,j) = W(1,1)*IMG(i-1,j-1) + W(1,2)*IMG(i-1,j) + W(1,3)*IMG(i-1,j+1) +...
    W(2,1)*IMG(i ,j-1) + W(2,2)*IMG(i ,j) + W(2,3)*IMG(i ,j+1) +...
    W(3,1)*IMG(i+1,j-1) + W(3,2)*IMG(i+1,j) + W(3,3)*IMG(i+1,j+1);
    end
    end
    end
  • Laplacian_Sharpen_Test.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    clear all; close all; clc;

    % -------------------------------------------------------------------------
    % Read PC image to Matlab
    IMG1 = imread('../../0_images/Lenna.jpg'); % 读取jpg图像
    IMG1 = rgb2gray(IMG1);
    h = size(IMG1,1); % 读取图像高度
    w = size(IMG1,2); % 读取图像宽度
    subplot(131);imshow(IMG1);title('【1】原图');

    % -------------------------------------------------------------------------
    IMG2 = Laplacian_Edge_Detector(IMG1);
    subplot(132);imshow(uint8(abs(IMG2)));title('【2】Laplacian边缘检测结果');

    % -------------------------------------------------------------------------
    IMG3 = uint8(double(IMG1) + IMG2);
    subplot(133);imshow(IMG3);title('【3】Laplacian锐化图像');
  • 调用Laplacian边缘检测函数,将边缘检测结果与原始图像叠加得到Laplacian锐化图像

    image-20241128193808677
  • 利用Laplacian算子可以获得比较细致的边界,反映了边界的许多细节信息,但反映的边界信息不是很清晰,有时会丢失一部分边缘的方向信息,造成不连续的检测边缘

2.Laplacian锐化的FPGA实现

  • Laplacian锐化处理分为以下几步:

    1. 将$3\times 3$窗口的像素与Laplacian算子进行卷积运算得到边缘检测结果,再与原始图像叠加得到Laplacian锐化的图像(叠加后公式可以化简为直接对滑窗进行加减运算

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      //----------------------------------------------------------------------
      reg [10:0] minute_data;
      reg [ 9:0] minus_data;

      always @(posedge clk)
      begin
      minute_data <= {matrix_p22,2'b0} + matrix_p22;
      minus_data <= matrix_p12 + matrix_p21 + matrix_p23 + matrix_p32;
      end

      //----------------------------------------------------------------------
      reg signed [11:0] pixel_data1;

      always @(posedge clk)
      begin
      pixel_data1 <= $signed({1'b0,minute_data}) - $signed({1'b0,minus_data});
      end
      image-20241128194255275
    2. Lapalcian锐化图像的灰度值可能小于0或大于255,为了防止数据溢出,如果灰度值小于0,则令其等于0;如果灰度值大于255,则令其等于255(这里判断方法的写法值得一学)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      reg             [7:0]           pixel_data2;

      always @(posedge clk)
      begin
      if(pixel_data1[11] == 1'b1)
      pixel_data2 <= 8'b0;
      else if(pixel_data1[10:8] != 3'b0)
      pixel_data2 <= 8'd255;
      else
      pixel_data2 <= pixel_data1[7:0];
      end
    3. 判断3×3窗口的中心像素是否位于图像边界, 如果位于图像边界, 则用3×3窗口的中心像素作为Laplacian锐化处理的结果

    image-20241128194856424
  • 仿真结果:

    image-20241128195508801


Reference

  • 《基于MATLAB与FPGA的图像处理教程》图书及其配套资料
欢迎来到ssy的世界