PotatoPie 4.0 实验教程(24) —— FPGA实现摄像头图像中心差分变换-Anlogic-安路论坛-FPGA CPLD-ChipDebug

PotatoPie 4.0 实验教程(24) —— FPGA实现摄像头图像中心差分变换

手机扫码

20240416075513933-1713225291635

链接直达

https://item.taobao.com/item.htm?ft=t&id=776516984361

为什么要对图像进行中心差分变换?

对图像进行中心差分变换的主要目的是计算图像中每个像素点的梯度。梯度在图像处理中是一个非常重要的概念,它可以用来描述图像中灰度变化的快慢和方向,常用于边缘检测、特征提取和图像增强等任务中。

具体来说,中心差分变换有以下几个作用:

  1. 边缘检测:梯度可以帮助我们找到图像中的边缘,因为在边缘处像素的灰度值通常会发生较大的变化。通过计算梯度,我们可以找到这些变化较大的区域,从而实现边缘检测。

  2. 特征提取:梯度可以用来提取图像中的一些重要特征,例如角点和边缘点。这些特征在图像匹配和目标识别等任务中非常有用。

  3. 图像增强:梯度可以用来增强图像的对比度和细节。通过计算梯度,我们可以调整图像的灰度级,使得图像中的细节更加清晰。

  4. 图像去噪:梯度可以帮助我们去除图像中的噪声。由于噪声通常会导致像素值的随机变化,因此在梯度计算中可以将这些随机变化过滤掉,从而实现去噪效果。

综上所述,通过对图像进行中心差分变换,我们可以获得图像中每个像素点的梯度信息,从而实现边缘检测、特征提取、图像增强和图像去噪等各种图像处理任务。

图像中心差分变换的算法

中心差分图像的计算公式是通过当前像素的后一像素和前一像素的差值除以2来得到的。具体公式如下所示:

其中, 表示图像的像素值, 表示当前像素的位置。表示后一像素值,表示前一像素值,这个公式描述了图像中每个像素的变化情况,可以用来分析图像的梯度或边缘信息。

中心差分图像的应用非常广泛,包括视频压缩、生物医学诊断、天文学、遥感、人脸识别等领域。

python实现图像的领域中心差分算法

这段代码使用了 OpenCV 库和 NumPy 库来实现图像的中心差分变换。首先,它定义了一个 central_difference 函数,该函数接受一个灰度图像作为输入,并返回中心差分后的图像。然后,它读取了一张彩色图像,将其转换为灰度图像,并应用了中心差分算法。最后,它将原始图像、灰度图像和中心差分后的图像水平叠加,并添加了标题,最终显示出来。

以下是代码的详细说明:

  1. 导入必要的库:

    import cv2
    import numpy as np
    import os
    • cv2:OpenCV 库,用于图像处理。
    • numpy:用于数值计算。
    • os:用于操作文件路径。
  2. 定义中心差分函数 central_difference

    def central_difference(image):
        # 使用公式 I(x) = (I(x+1) - I(x-1)) / 2 计算中心差分
        diff = np.zeros_like(image, dtype=np.float32)
        for i in range(1, image.shape[0] - 1):
            for j in range(1, image.shape[1] - 1):
                diff[i, j] = (image[i, j+1] - image[i, j-1]) / 2.0
        diff = np.abs(diff).astype(np.uint8)
        return diff

    此函数接收一个灰度图像作为输入,使用中心差分算法计算图像的梯度,并返回梯度图像。

  3. 获取当前文件的路径:

    current_file_path = __file__
    current_file_dir = os.path.dirname(current_file_path)

    使用 __file__ 内置变量获取当前脚本文件的路径,然后通过 os.path.dirname() 函数提取目录部分,并将结果存储在 current_file_dir 变量中。

  4. 读取彩色图像:

    image_color = cv2.imread(current_file_dir+'/Lena.jpg', cv2.IMREAD_COLOR)

    使用 cv2.imread() 函数读取名为 ‘Lena.jpg’ 的彩色图像文件,并将其存储在名为 image_color 的变量中。

  5. 将彩色图像转换为灰度图像:

    image_gray = cv2.cvtColor(image_color, cv2.COLOR_BGR2GRAY)

    使用 cv2.cvtColor() 函数将彩色图像 image_color 转换为灰度图像,并将结果存储在名为 image_gray 的变量中。

  6. 应用中心差分算法:

    result = central_difference(image_gray)

    调用 central_difference() 函数计算灰度图像 image_gray 的梯度,并将结果存储在名为 result 的变量中。

  7. 将图像水平叠加:

    combined_image = np.hstack((image_color, cv2.cvtColor(image_gray, cv2.COLOR_GRAY2BGR), cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)))

    使用 np.hstack() 函数将彩色图像、灰度图像和梯度图像水平叠加在一起,并将结果存储在名为 combined_image 的变量中。

  8. 添加标题:

    titles = ['Original Image', 'Gray Image', 'Central Difference Image']
    for i, title in enumerate(titles):
        cv2.putText(combined_image, title, (i * int(combined_image.shape[1] / len(titles)) + 20, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)

    使用 cv2.putText() 函数在合并后的图像上添加标题,以便区分不同部分。

  9. 显示合并后的图像:

    cv2.imshow('Combined Images', combined_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    使用 cv2.imshow() 函数显示合并后的图像,并使用 cv2.waitKey(0) 等待用户按下任意键后关闭窗口。

20240414185040439-image

matlab实现图像的领域中心差分算法

这段代码演示了如何利用 MATLAB 实现中心差分算法进行边缘检测,并对结果进行可视化显示。这段MATLAB 代码实现了以下功能:

  1. 读取一张彩色图像。
  2. 将彩色图像转换为灰度图像。
  3. 应用中心差分算法对灰度图像进行边缘检测。
  4. 对灰度图像和中心差分结果进行直方图均衡化。
  5. 将原始彩色图像、灰度图像、直方图均衡化的灰度图像以及中心差分结果的直方图均衡化图像水平叠加,并添加标题。

下面是对代码的详细解释:

  1. img_central_diff() 函数是主函数,它执行以下操作:

    • 获取当前脚本文件的路径。
    • 读取名为 ‘Lena.jpg’ 的彩色图像。
    • 将彩色图像转换为灰度图像。
    • 调用 central_difference() 函数应用中心差分算法。
    • 对灰度图像和中心差分结果进行直方图均衡化。
    • 将原始彩色图像、灰度图像和中心差分图像水平叠加,并添加标题。
    • 最后显示合并后的图像。
  2. central_difference() 函数实现了中心差分算法:

    • 使用公式 计算中心差分。
    • 循环遍历灰度图像的像素,对每个像素应用中心差分算法。
    • 将中心差分结果取绝对值并转换为 uint8 类型。
    • 返回中心差分结果。

20240415125206817-image

上面的代码可以看到合并后的灰度图太黑了,几乎看不到,要解决图像太黑的问题,可以考虑调整灰度图像和差分图像的亮度范围,使它们更接近彩色图像的亮度范围。这可以通过线性拉伸或直方图均衡化来实现。为了教程和简洁性在FPGA中我们不组合这些步骤。在下一教程《PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换》中我们也将学习直方图均衡化算法。

下面是对代码的修改,其中使用了直方图均衡化来调整灰度图像和差分图像的亮度范围:

function img_central_diff()
    % 读取图片
    current_file_path = mfilename('fullpath');
    current_file_dir = fileparts(current_file_path);
    disp(['current_file_dir: ', current_file_dir]);
    
    % 读取彩色图像
    image_color = imread(fullfile(current_file_dir, 'Lena.jpg'));

    % 将彩色图像转换为灰度图像
    image_gray = rgb2gray(image_color);

    % 应用中心差分算法
    result = central_difference(image_gray);

    % 直方图均衡化灰度图像和差分图像
    image_gray_eq = histeq(image_gray);
    result_eq = histeq(result);

    % 将图像水平叠加
    combined_image = cat(2, image_color, cat(3, image_gray_eq, image_gray_eq, image_gray_eq), cat(3, result_eq, result_eq, result_eq));

    % 添加标题
    titles = {'Original Image', 'Gray Image', 'Central Difference Image'};
    for i = 1:numel(titles)
        combined_image = insertText(combined_image, [i * size(combined_image, 2) / numel(titles) + 20, 30], titles{i}, 'FontSize', 24, 'TextColor', 'white', 'BoxColor', 'black', 'BoxOpacity', 0.7);
    end

    % 显示合并后的图像
    imshow(combined_image);
    title('Combined Images');
end

function result = central_difference(image)
    % 使用公式 I(x) = (I(x+1) - I(x-1)) / 2 计算中心差分
    diff = zeros(size(image), 'like', image);
    for i = 2:size(image, 1) - 1
        for j = 2:size(image, 2) - 1
            diff(i, j) = (image(i, j + 1) - image(i, j - 1)) / 2.0;
        end
    end
    diff = uint8(abs(diff));
    result = diff;
end

这段 MATLAB 代码实现了一个名为 img_central_diff 的函数,用于读取一张彩色图像,并对其进行灰度化、应用中心差分算法、直方图均衡化处理,然后将处理后的图像以及原始图像水平叠加并显示。以下是代码的详细说明:

  1. img_central_diff 函数:

    • 读取图片路径并显示:

      current_file_path = mfilename('fullpath');
      current_file_dir = fileparts(current_file_path);
      disp(['current_file_dir: ', current_file_dir]);

      使用 mfilename('fullpath') 获取当前脚本文件的完整路径,然后通过 fileparts() 函数提取目录部分,并显示目录路径。

    • 读取彩色图像并转换为灰度图像:

      image_color = imread(fullfile(current_file_dir, 'Lena.jpg'));
      image_gray = rgb2gray(image_color);

      使用 imread() 函数读取名为 ‘Lena.jpg’ 的彩色图像文件,并使用 rgb2gray() 函数将其转换为灰度图像。

    • 应用中心差分算法:

      result = central_difference(image_gray);

      调用名为 central_difference 的函数对灰度图像应用中心差分算法,并将结果存储在 result 变量中。

    • 直方图均衡化灰度图像和差分图像:

      image_gray_eq = histeq(image_gray);
      result_eq = histeq(result);

      使用 histeq() 函数对灰度图像和差分图像进行直方图均衡化处理。

    • 将图像水平叠加并添加标题:

      combined_image = cat(2, image_color, cat(3, image_gray_eq, image_gray_eq, image_gray_eq), cat(3, result_eq, result_eq, result_eq));

      使用 cat() 函数将原始图像、均衡化的灰度图像和均衡化的差分图像水平叠加。然后使用 insertText() 函数在叠加后的图像上添加标题。

    • 显示合并后的图像:

      imshow(combined_image);
      title('Combined Images');

      使用 imshow() 函数显示合并后的图像,并设置标题为 ‘Combined Images’。

  2. central_difference 函数:

    • 计算中心差分:

      diff = zeros(size(image), 'like', image);
      for i = 2:size(image, 1) - 1
          for j = 2:size(image, 2) - 1
              diff(i, j) = (image(i, j + 1) - image(i, j - 1)) / 2.0;
          end
      end

      使用循环遍历图像中的像素,并根据中心差分公式计算每个像素的差分值。

    • 将结果转换为 uint8 类型并返回:

      diff = uint8(abs(diff));
      result = diff;

      将计算得到的差分图像的像素值取绝对值并转换为 uint8 类型,然后返回结果。

调整后的图像如下

20240415131216913-image

FPGA工程解析

20240413191344445-image

demo18相比,只是多了一个img_central_diff的模块,也就是下面这一段代码,在从SDRAM读出来之后,经它处理后再输出hdmi_tx模块。

代码解析

核心算法就这一段,这一段代码中以红色分量为例i_r_d是前一周期的像素值,i_r为当前像素值,二者相减,然后右移一位即为除以2。

其它请参考代码中的详细注释。

管脚约束

PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

时序约束

PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

实验结果

像机噪点有点多呃。

20240406210704716-image

请登录后发表评论

    没有回复内容