本帖最后由 正点原子运营 于 2021-10-30 10:20 编辑
1)实验平台:正点原子新起点V2FPGA开发板
2) 章节摘自【正点原子】《新起点之FPGA开发指南 V2.1》
3)购买链接:https://detail.tmall.com/item.htm?id=609758951113
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_xinqidian(V2).html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:712557122
第四十九章 OV5640摄像头HDMI灰度显示实验
前面的实验介绍了OV5640摄像头的HDMI显示实验,而在数字图像处理领域YUV是一种常用的图像格式,其特点是将亮度和色度进行分离,更适合运用于图像处理领域。在本次实验中,将摄像头采集的RGB565格式数据到转换为YUV格式的数据,转换后的灰度数据送到HDMI显示器显示。
本章包括以下几个部分:
48.1简介
48.2实验任务
48.3硬件设计
48.4程序设计
48.5下载验证
49.1简介
人眼中的锥状细胞是负责彩色视觉的传感器,可分为三个主要的感知类别,分别对应红色、绿色、蓝色,而人眼看到的彩色实际上是红、绿、蓝三原色的各种组合。之前所有的图像显示实验用到的RGB就是以红、绿、蓝为三原色的颜色空间模型,通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。
YUV(YCbCr)是欧洲电视系统所采用的一种颜色编码方法。‘Y’表示明亮度(Luminance或Luma),也就是灰阶值;‘U’和‘V’表示色度,用于描述影像的饱和度和色调。RGB与YUV的转换实际上是色彩空间的转换,即将RGB的三原色色彩空间转换为YUV所表示的亮度与色度的色彩空间模型。YUV 主要应用在模拟系统中,而 YCbCr 是通过 YUV 信号的发展,并通过校正的主要应用在数字视频中的一种编码方法。YUV适用于PAL和SECAM彩色电视制式,而YCrCb适用于计算机用的显示器。 一般意义上 YCbCr 即为 YUV 信号,没有严格的划分。 CbCr 分别为蓝色色度分量、红色色度分量。
RGB着重于人眼对色彩的感应,YUV则着重于视觉对于亮度的敏感程度。使用YUV描述图像的好处在于以下两个方面:
(1)亮度(Y)与色度(U、V)是独立的;
(2)人眼能够识别数千种不同的色彩,但只能识别20多种灰阶值,采用YUV标准可以降低数字彩色图像所需的储存容量。因而YUV在数字图像处理中是一种很常用的颜色标准。
YUV格式运用最多是以下两种格式:
(1)YUV4:4:4
在YUV4:4:4格式中,YUV三个信道的采样率相同。因此在生成的图像里,每个像素都有各自独立的三个分量,每个分量通常为8bit,故每个像素占用3个字节。下图为YUV444单个像素的模型图,可以看出,每个Y都对应一组U、V数据,共同组成一个像素。
图 49.1.1 单个V444的素
(2)YUV4:2:2
在YUV4:2:2格式中,U和V的采样率是Y的一半(两个相邻的像素共用一对U、V数据)。如下图所示,图中包含两个相邻的像素。第一个像素的三个YUV分量分别是Y1、U1、V1,第二个像素的三个YUV分量分别是Y2、U1、V1,两个像素共用一组U1、V1。
图 49.1.2 两个相邻的YUV422像素
YUV4:4:4格式和YUV4:2:2格式的数据流也是不同的。如一组连续的四个像素P1、P2、P3、P4,采用YUV444的采样格式时,数据流为Y0 U0 V0、Y1 U1 V1、Y2 U2 V2、Y3 U3 V3,每组数据代表一个像素点。而用YUV422的采样格式时,数据流为Y0 U0 Y1 V1、Y2 U2 Y3 V3。其中,Y0 U0 Y1 V1表示P1、P2两个像素,Y2 U2 Y3 V3表示P3、P4两个像素。本次实验运用的是YUV4:4:4格式。
一般意义上 YCbCr 即为 YUV 信号,没有严格的划分。大家通常说的YUV就是指Ycbcr。 CbCr 分别为蓝色色度分量、红色色度分量。下面为 RGB 与 YCbCr 色彩空间转换的算法公式, RGB 转 YCbCr 的公式如下所示:
图 49.1.3 RGB 转 YcbCr算法
由于 Verilog HDL 无法进行浮点运算,因此使用扩大 256 倍,再向右移 8Bit的方式,来转换公式,如下所示:
图 49.1.4 RGB 转 YcbCr算法
为了防止运算过程中出现负数,对上述公式进行进一步变换,得到如下公式:
图 49.1.5 RGB 转 YcbCr算法
实际上OV5640本身支持输出RGB、YUV格式的数据,本章节实验是着重于RGB转YUV的HDL算法实现,因此把摄像头设置为RGB565格式。当需要显示器显示灰度图时,只需要将转换后的Y值作为R、G、B三原色通道的输入就可以实现了。
49.2实验任务
本节实验任务是使用新起点开发板达到OV5640摄像头采集RGB565格式的数据,RGB565格式的数据通过算法转换,将数据格式转换为YCbCr格式,然后通过HDMI显示器实时显示灰度图的目的。
49.3硬件设计
本章节中硬件设计与OV5640的HDMI显示实验完全相同,此处不再赘述。
49.4程序设计
根据实验任务,首先设计如图 49.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头HDMI显示实验”的整体架构。本次实验包括以下模块:时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、摄像头采集模块、图像处理模块和HDMI顶层模块。其中时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、摄像头采集模块和HDMI顶层模块本次实验没有做任何修改,这些模块在“OV5640摄像头HDMI显示实验”中已经说明过,这里不再详述,本次实验只是添加了图像处理模块。
OV5640摄像头HDMI灰度显示系统框图如下图所示:
图 49.4.1 顶层系统框图
由上图可知,时钟模块(pll和pll_hdmi)为HDMI顶层模块、SDRAM控制模块以及IIC驱动模块提供驱动时钟。IIC驱动模块和IIC配置模块控制着传感器初始化的开始与结束,传感器初始化完成后将采集到的数据写入摄像头采集模块。数据在摄像头采集模块处理完成后写入图像处理模块,图像处理模块将摄像头数据进行处理后存入SDRAM控制模块。顶层模块从SDRAM控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在SDRAM和传感器都初始化完成之后才开始输出数据的,避免了在SDRAM初始化过程中向里面写入数据。
顶层模块代码如下所示:
FPGA顶层模块(ov5640_hdmi_yuv)例化了以下八个模块:时钟模块1(pll)、时钟模块2(pll_hdmi)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov5640_rgb565_cfg)、图像采集模块(cmos_capture_data)、图像处理模块(vip)、SDRAM控制模块(sdram_top)和HDMI顶层模块(hdmi_top)。
时钟模块:时钟模块通过调用PLL IP核实现,共输出5个时钟,频率分别为100M时钟、100M偏移-75度时钟、50M时钟、71Mhz时钟和355M时钟(HDMI像素时钟的5倍频)。其中pll 产生了50M时钟、100M时钟和100M偏移-75度时钟,pll_hdmi 产生了71Mhz时钟和355M时钟,这里之所以用两个锁相环是因为HDMI所用的时钟71Mhz与SDRAM控制模块使用的100M时钟不是整数倍,使用一个锁相环不符合设计要求。100Mhz时钟作为SDRAM控制模块的驱动时钟,100M偏移-75度时钟用来输出给外部SDRAM芯片使用,50Mhz时钟作为I2C驱动模块的驱动时钟,71Mhz时钟和355M时钟(HDMI像素时钟的5倍频)负责驱动HDMI顶层模块。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV5640 SCCB接口总线,用户可根据该模块提供的用户接口可以很方便的对OV5640的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
I2C配置模块(i2c_ov5640_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV5640的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对OV5640传感器的初始化。
图像采集模块(cmos_capture_data):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。OV5640和OV7725图像输出时序非常相似,有关该模块的详细介绍请大家参考“OV7725摄像头LCD显示实验”章节。
图像处理模块(vip):对采集后的图像数据进行处理,并将处理后的数据存入SDRAM控制模块。
SDRAM控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存图像传感器输出的图像数据。有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供显示器参数、场同步信号和数据请求信号。关HDMI顶层模块的详细介绍请大家参考“OV5640摄像头HDMI显示实验”章节。
图像处理模块负责图像数据的格式转换,代码如下:
- 1 module vip(
- 2 //module clock
- 3 input clk , // 时钟信号
- 4 input rst_n , // 复位信号(低有效)
- 5
- 6 //图像处理前的数据接口
- 7 input pre_frame_vsync,
- 8 input pre_frame_hsync,
- 9 input pre_frame_de ,
- 10 input [15:0] pre_rgb ,
- 11 input [10:0] xpos ,
- 12 input [10:0] ypos ,
- 13
- 14 //图像处理后的数据接口
- 15 output post_frame_vsync, // 场同步信号
- 16 output post_frame_hsync, // 行同步信号
- 17 output post_frame_de , // 数据输入使能
- 18 output [15:0] post_rgb // RGB565颜色数据
- 19 );
- 20
- 21 //wire define
- 22 wire [ 7:0] img_y;
- 23
- 24 //*****************************************************
- 25 //** main code
- 26 //*****************************************************
- 27
- 28 assign post_rgb = {img_y[7:3],img_y[7:2],img_y[7:3]};
- 29
- 30 //RGB转YCbCr模块
- 31 rgb2ycbcr u_rgb2ycbcr(
- 32 //module clock
- 33 .clk (clk ), // 时钟信号
- 34 .rst_n (rst_n ), // 复位信号(低有效)
- 35 //图像处理前的数据接口
- 36 .pre_frame_vsync (pre_frame_vsync), // vsync信号
- 37 .pre_frame_hsync (pre_frame_hsync), // href信号
- 38 .pre_frame_de (pre_frame_de ), // data enable信号
- 39 .img_red (pre_rgb[15:11] ),
- 40 .img_green (pre_rgb[10:5 ] ),
- 41 .img_blue (pre_rgb[ 4:0 ] ),
- 42 //图像处理后的数据接口
- 43 .post_frame_vsync(post_frame_vsync), // vsync信号
- 44 .post_frame_hsync(post_frame_hsync), // href信号
- 45 .post_frame_de (post_frame_de), // data enable信号
- 46 .img_y (img_y),
- 47 .img_cb (),
- 48 .img_cr ()
- 49 );
- 50
- 51 endmodule
复制代码
代码的第28行表示对转换后的8bit灰度数据进行位拼接,形成16bit的RGB565格式的数据输出。
代码的第31行至49行是对灰度转换模块的例化,在该模块以摄像头采集的16位RGB565红、绿、蓝三原色数据作为输入数据,通过算法实现RGB到YCbCr的转换,并输出8位灰度数据,并输出数据输出使能信号。
灰度转换模块负责将RGB565格式的图像数据转换为YCbCr格式数据,代码如下:
在RGB转成YUV格式的算法换算过程中数据都是以8位的数据进行的,因而我们需要将RGB565格式的数据转换成RGB888的格式,如代码第48至50行所示,此处采用的是高位补充低位的方法;下面就是进行RGB565转YCbCr算法的HDL实现:第一步,先计算出前面公式中括号里每一个乘法的乘积,如代码第78至101行所示;第二步,计算出Y、Cb、Cr括号内的值,代码104至116行;第三步,右移 8bit,由于 Step2 计算结果为 16bit,因此直接提取高8位即可,代码如119至130行所示。
实际上从第一步到第三步的运算,均直接通过寄存器描述,没有顾虑行场有效时序等。但在实际电路中会有一个数据流上的先后顺序,这三步操作同时对连续数据进行处理,通过这种方式实现硬件加速的方法称为流水线设计。前面计算出 Y、Cb、Cr 我们消耗了step1、step2、step3这三个时钟,因此需要将输入的行场信号、使能信号同步移动 3 个时钟,如代码第133至144行。
49.5下载验证
编译完工程之后就可以开始下载程序了。将OV5640摄像头模块插在新起点开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来下载程序,验证OV5640 HDMI灰度显示功能。下载完成后观察HDMI显示器显示的灰度图案如下图所示,说明OV5640 HDMI灰度显示程序下载验证成功。
图 49.5.1 HDMI实时显示灰度图像 |