PotatoPie 4.0 实验教程(20) —— FPGA实现摄像头图像转灰度图像(RGB2Gray)-Anlogic-安路社区-FPGA CPLD-ChipDebug

PotatoPie 4.0 实验教程(20) —— FPGA实现摄像头图像转灰度图像(RGB2Gray)

手机扫码

20240416075513933-1713225291635

链接直达

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

什么是灰度图?

灰度图是一种只包含灰度信息(亮度信息)而不包含彩色信息的图像。在灰度图中,每个像素的亮度值表示图像中对应位置的亮度级别,通常用 0 到 255 之间的整数值表示,0 表示黑色,255 表示白色,中间的值表示不同程度的灰度。

灰度图是由彩色图像经过灰度化处理得到的,灰度化处理是将彩色图像的 RGB(红绿蓝)三个通道的颜色值转换为单一的灰度值的过程。常见的灰度化方法包括将 RGB 三个通道的像素值按照一定的权重进行加权平均,或者采用其他算法,如最大值法、最小值法等。

灰度图常用于图像处理、计算机视觉、模式识别等领域。与彩色图像相比,灰度图具有更低的存储空间和处理复杂度,因此在一些应用中更加高效。例如,人脸识别、图像检索、医学图像分析等领域常常使用灰度图来简化图像处理过程。

为什么要使用灰度图?

使用灰度图有几个重要的原因:

  1. 简化处理:灰度图仅包含亮度信息,相比彩色图像,其数据量更小,处理起来更加简单和高效。这使得在一些应用中,如图像处理、模式识别、计算机视觉等,可以节省计算资源和时间。

  2. 降低复杂性:灰度图消除了彩色信息,使图像更加简洁,更容易理解和分析。在一些应用中,如医学图像分析、地质图像分析等领域,灰度图可以使得图像的特征更加明显,更容易被专业人员识别和分析。

  3. 增强对比度:在某些情况下,灰度图比彩色图更容易展示图像的细节和结构,因为彩色信息可能会分散注意力,而灰度图则能够集中观察者的注意力于图像的亮度变化和纹理细节上。

  4. 适应特定应用:有些应用只需要图像中的亮度信息而不需要彩色信息,例如,自动识别、人脸识别、目标检测等应用可以在灰度图上更有效地进行,因为亮度信息往往是决定图像中对象特征的关键因素。

  5. 减少数据存储和传输开销:由于灰度图的数据量比彩色图小很多,因此在存储和传输方面具有更高的效率,尤其是在需要大量图像数据的场景中,如视频流传输、图像数据存档等。

灰度图公式

加权平均法是一种常用的灰度化方法,其基本原理是将彩色图像的每个像素的 RGB 值按照一定的权重进行线性组合,得到一个灰度值。通常情况下,人眼对不同颜色的敏感程度不同,因此在进行灰度化时,可以根据人眼的感知特性,对不同颜色的权重进行调整。

加权平均法的一般公式如下所示:

20240406175651123-image

其中, 分别表示彩色图像的红色、绿色和蓝色通道的像素值, 表示生成的灰度图像的像素值。红色通道的权重是 0.299,绿色通道的权重是 0.587,蓝色通道的权重是 0.114。这些权重是根据人眼对不同颜色的感知程度而确定的。这些权重的和通常为 1,以确保灰度化后的像素值范围在 0255 之间。

这种加权平均法的优点是简单易懂,并且与人眼的感知特性较为吻合,因此在许多应用中被广泛使用。

 用python实现RGB转Gray灰度算法

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import os

# 获取当前脚本所在目录
current_file_dir = os.path.dirname(os.path.abspath(__file__))
# 图片文件路径
img_path = os.path.join(current_file_dir, 'Lena.jpg')

# 读取图像
img = mpimg.imread(img_path)

# 提取图像尺寸
rows, cols, _ = img.shape

# 创建灰度图像数组
gray_img = [[0 for _ in range(cols)] for _ in range(rows)]

# 计算灰度值
for i in range(rows):
    for j in range(cols):
        r, g, b = img[i, j]
        gray_img[i][j] = 0.299 * r + 0.587 * g + 0.114 * b

# 显示原始图像
plt.figure()
plt.imshow(img)
plt.title('Original Image')
plt.axis('off')

# 显示灰度图像
plt.figure()
plt.imshow(gray_img, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')

# 显示图像
plt.show()

这个代码片段会读取名为 Lena.jpg 的图片,将其转换为灰度图,并显示原始图像以及转换后的灰度图像。

以下是代码的详细说明:

  1. 导入必要的库:

    • matplotlib.pyplot:用于绘制图像和图形。
    • matplotlib.image:用于读取图像文件。
    • os:用于操作文件路径。
  2. 获取当前脚本所在目录: 使用 os.path.abspath(__file__) 获取当前脚本的绝对路径,然后使用 os.path.dirname() 获取该路径所在的目录。

  3. 定义图像文件路径: 使用 os.path.join() 将当前目录路径与图像文件名拼接,生成图像文件的完整路径。

  4. 读取图像: 使用 mpimg.imread() 函数读取图像文件,并将其存储在名为 img 的变量中。

  5. 提取图像尺寸: 使用 shape 属性获取图像的行数、列数和通道数,分别存储在 rowscols 变量中。

  6. 创建灰度图像数组: 创建一个与原始图像尺寸相同的二维数组 gray_img,用于存储灰度图像的像素值。

  7. 计算灰度值: 遍历原始图像的每个像素,通过加权平均的方式计算灰度值,并将结果存储在灰度图像数组 gray_img 中。

  8. 显示原始图像: 使用 plt.imshow() 函数显示原始图像,设置标题为 ‘Original Image’,并关闭坐标轴显示。

  9. 显示灰度图像: 使用 plt.imshow() 函数显示灰度图像,设置 cmap='gray' 参数以显示灰度图像,并设置标题为 ‘Grayscale Image’,关闭坐标轴显示。

  10. 显示图像: 使用 plt.show() 函数显示图像。

这段代码演示了如何使用 Matplotlib 库将彩色图像转换为灰度图像,并使用 pyplot 模块显示原始图像和转换后的灰度图像。

在powershell中输入如下命令,需指定rgb2gray.py的绝对路径。

20240415102337379-image

20240414102347146-image

 用Matlab实现RGB转Gray灰度算法

这段代码是用 MATLAB 编写的,用于将彩色图像转换为灰度图像,并显示原始图像和转换后的灰度图像。以下是代码的详细说明:

  1. 获取当前脚本文件的路径: 使用 mfilename('fullpath') 函数获取当前脚本文件的完整路径,并将结果存储在 current_file_path 变量中。

  2. 从绝对路径中提取目录: 使用 fileparts() 函数从当前脚本文件的完整路径中提取目录部分,并将结果存储在 current_file_dir 变量中。

  3. 读取图片: 使用 imread() 函数读取名为 ‘Lena.jpg’ 的图片文件,并将其存储在名为 img 的变量中。

  4. 提取图像尺寸: 使用 size() 函数获取图像的行数、列数和通道数,并将结果存储在 rowscols 变量中。

  5. 创建灰度图像数组: 使用 zeros() 函数创建一个与原始图像尺寸相同的二维数组 gray_img,用于存储灰度图像的像素值。

  6. 计算灰度值: 使用嵌套的 for 循环遍历原始图像的每个像素,将每个像素的红、绿、蓝通道值转换为灰度值,并将结果存储在灰度图像数组 gray_img 中。

  7. 显示原始图像: 使用 imshow() 函数显示原始图像,设置标题为 ‘Original Image’,并关闭图像的坐标轴显示。

  8. 显示灰度图像: 使用 imshow() 函数显示灰度图像,通过空的方括号 [] 自动调整显示范围,设置标题为 ‘Grayscale Image’,并关闭图像的坐标轴显示。

这段代码演示了如何使用 MATLAB 将彩色图像转换为灰度图像,并使用 MATLAB 图形界面显示原始图像和转换后的灰度图像。

matlab运行脚本时会出现类似下图的错误,提示rgb2gray.m已在matlab路径中存在,直接点更改文件夹即可。

20240415090541278-image

20240415102643935-image

FPGA工程解析

工程数据流图

工程层次图

20240416083204511-image

代码解析

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

rgb2gray u_rgb2gray
(
    .i_clk(clk_pixel),  
    .i_rst_n(sys_rst_n),    
    .i_hs(VGA_HS),     
    .i_vs(VGA_VS),     
    .i_de(VGA_DE),       
    .i_r(VGA_RGB[23:16]),
    .i_g(VGA_RGB[15:8]),
    .i_b(VGA_RGB[7:0]),    
    .o_gray_hs(gray_hs),    
    .o_gray_vs(gray_vs),    
    .o_gray_de(gray_de),
    .o_gray_data(gray_data) 
);

跟上一个教程一样,要在不带浮点DSP的FPGA中实现,先将浮点转定点,老办法等式右边先乘256进行四舍五入小数转整数,然后再除256。最终公式如下:

20240406180724899-image

在这个公式中, 表示彩色图像的红色、绿色和蓝色通道的像素值, 表示生成的灰度图像的像素值。整数权重 77,151,28 是原始权重 0.299×256,0.587×256,0.114×256 分别放大256倍后取整得到的结果。将结果除以256是因为放大了256倍,相当于整体右移8位,所以需要将结果右移8位。即:

Y = (77 * R + 150 * G + 29 * B)>>8

核心代码就下面两段:

先做各个分量的乘法计算,

r_d0 <= 77  * i_r;
g_d0 <= 150 * i_g;
b_d0 <= 29  * i_b;

然后求和,

gray_d0 <= r_d0 + g_d0 + b_d0;

跟demo19一样,分成两步也是为了时序。同样也需要将行场信号打一拍。

管脚约束

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

时序约束

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

实验结果

跟YCbCr的Y图像有点像,但是看起来对比度要比Y图像质量高一点。

20240406183318518-1712399584620

请登录后发表评论

    没有回复内容