|
本帖最后由 正点原子 于 2021-1-23 15:31 编辑
1)实验平台:正点原子达芬奇FPGA开发板
2) 章节摘自【正点原子】达芬奇之FPGA开发指南
3)购买链接:https://detail.tmall.com/item.htm?id=624335496505
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_dafenqi.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)对正点原子FPGA感兴趣的同学可以加群讨论:905624739 点击加入:
第四十六章基于OV5640的二值化实验
在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,还能凸显出目标的轮廓。图像二值化在计算机视觉、图像分割以及人工智能等方面有着广泛应用。在本章节将进行基于OV5640的二值化实验。
本章包括以下几个部分:
4646.1简介
46.2实验任务
46.3硬件设计
46.4程序设计
46.5下载验证
46.1简介
图像二值化(Image Binarization)就是将图像上的像素点的灰度值设置为最大(白色)或最小(黑色),也就是将整个图像呈现出明显的黑白效果的过程。这里以8bit表示的灰度图像为例(灰度值的范围为0~255),二值化就是通过选取适当的阈值,与图像中的256个亮度等级进行比较。亮度高于阈值的像素点设置为白色(255),低于阈值的像素点设置为黑色(0),从而明显地反映出图像的整体和局部特征。
在数字图像处理中,二值图像占有非常重要的地位,特别是在实时的图像处理中,通过二值图像来构成的系统有很多。要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样有利于在对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值用255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。
实现二值化有两种方法,一种是手动指定一个阈值,通过阈值来进行二值化处理;另一种是一个自适应阈值二值化方法(OTSU算法和Kittle算法等)。使用第一种方法计算量小速度快,但在处理不同图像时颜色分布差别很大;使用第二种方法适用性强,能直接观测出图像的轮廓,但计算相对更复杂。本章节实验将使用第一种方法来实现图像的二值化。
如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用制定阈值的方法,可以得到比较有效的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阈值选取技术来分割该图像。
46.2实验任务
本节实验任务是在达芬奇开发板上使用OV5640摄像头采集RGB565数据,将数据转化成Ycbcr格式,然后进行灰度二值化,并通过HDMI显示。
46.3硬件设计
本章节中硬件设计与“OV5640摄像头HDMI显示实验”完全相同,此处不再赘述。
46.4程序设计
根据实验任务,首先设计如图 46.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头HDMI灰度显示实验”的整体架构。本次实验包括以下模块:时钟模块、图像分辨率设置模块、DDR控制器模块、摄像头驱动模块、图像处理模块和HDMI顶层模块。其中时钟模块、DDR控制器模块、HDMI顶层模块、图像分辨率设置模块和摄像头驱动模块没有做任何修改,这些模块在“OV5640摄像头HDMI显示实验”中已经说明过,这里不再详述,本次实验只对图像处理模块做了修改。
OV5640的二值化实验系统框图如下图所示:
图 46.4.1 顶层系统框图
由上图可知,时钟模块(clk_wiz_0)为HDMI顶层模块、DDR控制模块以及OV5640驱动模块提供驱动时钟。OV5640驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后将采集到的数据写入图像处理模块。图像处理模块将摄像头数据进行处理后存入DDR控制模块。顶层模块从DDR控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
顶层模块的原理图如下图所示:
图 46.4.2 顶层模块原理图
FPGA顶层模块(ov5640_hdmi_img_binarization)例化了以下五个模块:时钟模块(clk_wiz_0)、OV5640驱动模块(ov5640_dri)、图像处理模块(vip)、DDR控制模块(ddr3_top)和HDMI顶层模块(hdmi_top)。
时钟模块(clk_wiz_0):时钟模块通过调用MMCM IP核实现,共输出4个时钟,频率分别为200Mhz(DDR3参考时钟)、50Mhz时钟、65Mhz时钟和325M时钟(HDMI像素时钟的5倍频)。200Mhz时钟作为DDR控制模块的参考时钟,由MIG IP核产生的ui_clk(本次设计为100Mhz)作为DDR控制模块的驱动时钟,50Mhz时钟作为OV5640驱动模块驱动时钟,65Mhz时钟和325M时钟(HDMI像素时钟的5倍频)负责驱动HDMI顶层模块。
OV5640驱动模块(ov5640_dri):OV5640驱动模块负责驱动OV5640 SCCB接口总线,将像素时钟驱动下的传感器输出的场同步信号、行同步信号以及8位数据转换成DDR读写控制模块的写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。
图像处理模块(vip):对采集后的图像数据进行处理,并将处理后的数据存入DDR控制模块。
DDR控制模块(ddr3_top):DDR读写控制器模块负责驱动DDR片外存储器,缓存图像传感器输出的图像数据。该模块将MIG IP核复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。
有关DDR控制模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供显示器参数、场同步信号和数据请求信号。关HDMI顶层模块的详细介绍请大家参考“OV5640摄像头HDMI显示实验”章节。
VIP模块框图如下图所示:
图 46.4.3 vip模块框图
vip模块例化了RGB转YCbCr模块(rgb2ycbcr)、中值滤波模块(vip_gray_median_jilter)和二值化模块(binarization)。RGB转YCbCr模块负责将摄像头采集的RGB565格式数据到转换为YUV格式的数据。中值滤波模块负责将YUV格式的视频图像进行中值滤波后输出。二值化模块负责将中值滤波后的视频图像进行二值化处理再输出。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。
vip模块原理图如下图所示:
图 46.4.4 vip模块原理图
如上图所示,摄像头采集到16位rgb565输入vip模块,经过“rgb2ycbcr”模块转化为8位的yuv444数据,然后在将转化后的灰度数据(img_y)作为“vip_gray_median_filter”模块的输入,对灰度进行中值滤波处理,再将中值滤波后的数据输入进二值化模块,对数据进行二值化处理,最后输出经过二值化处理后的灰度数据“monoc”。
图像处理模块负责图像数据的格式转换,代码如下:
- 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 );
- 22
- 23 //wire define
- 24 wire [ 7:0] img_y;
- 25 wire [ 7:0] post_img_y;
- 26 wire [15:0] post_rgb;
- 27 wire post_frame_vsync;
- 28 wire post_frame_hsync;
- 29 wire post_frame_de;
- 30 wire pe_frame_vsync;
- 31 wire pe_frame_href;
- 32 wire pe_frame_clken;
- 33 wire ycbcr_vsync;
- 34 wire ycbcr_hsync;
- 35 wire ycbcr_de;
- 36 wire monoc;
- 37 //*****************************************************
- 38 //** main code
- 39 //*****************************************************
- 40
- 41 assign post_rgb = {16{monoc}};
- 42
- 43 //RGB转YCbCr模块
- 44 rgb2ycbcr u_rgb2ycbcr(
- 45 //module clock
- 46 .clk (clk ), // 时钟信号
- 47 .rst_n (rst_n ), // 复位信号(低有效)
- 48 //图像处理前的数据接口
- 49 .pre_frame_vsync (pre_frame_vsync), // vsync信号
- 50 .pre_frame_hsync (pre_frame_hsync), // href信号
- 51 .pre_frame_de (pre_frame_de ), // data enable信号
- 52 .img_red (pre_rgb[15:11] ),
- 53 .img_green (pre_rgb[10:5 ] ),
- 54 .img_blue (pre_rgb[ 4:0 ] ),
- 55 //图像处理后的数据接口
- 56 .post_frame_vsync(pe_frame_vsync), // vsync信号
- 57 .post_frame_hsync(pe_frame_href), // href信号
- 58 .post_frame_de (pe_frame_clken), // data enable信号
- 59 .img_y (img_y), //灰度数据
- 60 .img_cb (),
- 61 .img_cr ()
- 62 );
- 63
- 64 //灰度图中值滤波
- 65 vip_gray_median_filter u_ vip_gray_median_filter (
- 66 .clk (clk),
- 67 .rst_n (rst_n),
- 68
- 69 //预处理图像数据
- 70 .pe_frame_vsync (pe_frame_vsync), // vsync信号
- 71 .pe_frame_href (pe_frame_href), // href信号
- 72 .pe_frame_clken (pe_frame_clken), // data enable信号
- 73 .pe_img_y (img_y),
- 74
- 75 //处理后的图像数据
- 76 .pos_frame_vsync (ycbcr_vsync), // vsync信号
- 77 .pos_frame_href (ycbcr_hsync), // href信号
- 78 .pos_frame_clken (ycbcr_de), // data enable信号
- 79 .pos_img_y (post_img_y) //中值滤波后的灰度数据
- 80 );
- 81
- 82 //二值化模块
- 83 binarization u_binarization(
- 84 .clk (clk),
- 85 .rst_n (rst_n),
- 86 //图像处理前的数据接口
- 87 .ycbcr_vsync (ycbcr_vsync),
- 88 .ycbcr_hsync (ycbcr_hsync),
- 89 .ycbcr_de (ycbcr_de),
- 90 .luminance (post_img_y),
- 91 //图像处理后的数据接口
- 92 .post_vsync (post_frame_vsync),
- 93 .post_hsync (post_frame_hsync),
- 94 .post_de (post_frame_de),
- 95 .monoc (monoc) //二值化后的数据
- 96 );
- 97 endmodule
复制代码
代码的第37行表示对二值化后的1bit灰度数据进行位拼接,形成16bit的RGB565格式的数据输出。
代码的第39行至58行是对灰度转换模块的例化,在该模块以摄像头采集的16位RGB565红、绿、蓝三原色数据作为输入数据,通过算法实现RGB到YCbCr的转换,并输出8位灰度数据,并输出数据输出使能信号。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。
代码的第61行至75行是对中值滤波模块的例化,该模块负责将YUV格式的视频图像进行中值滤波后输出。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。
代码的第83行至96行是对二值化模块的例化,该模块主要是根据设定阈值,将图像化分为黑白两种颜色。
中值滤波模块和灰度转换模块在前面的章节已经讲解过,本次实验不在讲述。本次实验重点讲解二值化模块,下面是二值化模块的代码。
- 1 module binarization(
- 2 //module clock
- 3 input clk , // 时钟信号
- 4 input rst_n , // 复位信号(低有效)
- 5
- 6 //图像处理前的数据接口
- 7 input ycbcr_vsync , // vsync信号
- 8 input ycbcr_hsync , // hsync信号
- 9 input ycbcr_de , // data enable信号
- 10 input [7:0] luminance ,
- 11
- 12 //图像处理后的数据接口
- 13 output post_vsync , // vsync信号
- 14 output post_hsync , // hsync信号
- 15 output post_de , // data enable信号
- 16 output reg monoc // monochrome(1=白,0=黑)
- 17 );
- 18
- 19 //reg define
- 20 reg ycbcr_vsync_d;
- 21 reg ycbcr_hsync_d;
- 22 reg ycbcr_de_d ;
- 23
- 24 //*****************************************************
- 25 //** main code
- 26 //*****************************************************
- 27
- 28 assign post_vsync = ycbcr_vsync_d ;
- 29 assign post_hsync = ycbcr_hsync_d ;
- 30 assign post_de = ycbcr_de_d ;
- 31
- 32 //二值化
- 33 always @(posedge clk or negedge rst_n) begin
- 34 if(!rst_n)
- 35 monoc <= 1'b0;
- 36 else if(luminance > 8'd64) //阈值
- 37 monoc <= 1'b1;
- 38 else
- 39 monoc <= 1'b0;
- 40 end
- 41
- 42 //延时1拍以同步时钟信号
- 43 always@(posedge clk or negedge rst_n) begin
- 44 if(!rst_n) begin
- 45 ycbcr_vsync_d <= 1'd0;
- 46 ycbcr_hsync_d <= 1'd0;
- 47 ycbcr_de_d <= 1'd0;
- 48 end
- 49 else begin
- 50 ycbcr_vsync_d <= ycbcr_vsync;
- 51 ycbcr_hsync_d <= ycbcr_hsync;
- 52 ycbcr_de_d <= ycbcr_de ;
- 53 end
- 54 end
- 55
- 56 endmodule
复制代码
二值化的主要原理就是,给出一个设定的阈值,将灰度值与该阈值比较,若灰度值大于该阈值则monoc为1,若小于阈值,则monoc为0,如代码第33到40行。理论上阈值可以是0到255中的任意值,但阈值过大,会提取多余的部分;而阈值过小,又会丢失所需的部分,因此阈值选取就是一个很重要的步骤。
在代码第43到54行,通过寄存操作对gray_vsync、gray_clken等信号作了一个时钟周期的延迟。这是因为在进行二值判定时消耗了一个时钟,因此相应的同步信号也要延迟一个时钟周期,以实现与数据的同步。
46.5下载验证
编译完工程之后就可以开始下载程序了。将OV5640摄像头模块插在达芬奇开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI_B插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,下载完成后观察HDMI显示器显示的二值化后的图案。如下图所示:
图 46.5.1HDMI实时显示二值化图像
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|