第五十三章 基于OV5640摄像头二值化实验
二值图像在数字图像处理中起着非常重要的作用。图像的二值化大大降低了图像中的数据量,突出了目标的轮廓。图像二值化广泛应用于计算机视觉、图像分割和人工智能。本章将基于OV二值化实验5640。 本章包括以下部分: 51.1 简介 51.2 实验任务 51.3 硬件设计 51.4 程序设计 51.5 下载验证 ? 53.1 简介 图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为最大(白色)或最小(黑色),也就是将整个图像呈现出明显的黑白效果的过程。这里以8bit以灰度图像为例(灰度值的范围为0~255)二值化是通过选择合适的阈值来比较图像中的256个亮度等级。亮度高于阈值的像素点设置为白色(255),低于阈值的像素点设置为黑色(0),明显反映了图像的整体和局部特征。 在数字图像处理中,二值图像占着非常重要的作用,特别是在实时图像处理中,有许多系统由二值图像组成。为了处理和分析二值图像,首先是灰度图像二值,获得二值图像,有利于进一步处理图像,图像收集性质仅与0或255点的位置有关,不再涉及像素的多级值,使处理简单。为了获得理想的二值图像,通常使用封闭和连接的边界来定义不重叠的区域。所有灰度大于或等于阈值的像素都被确定为特定物体,灰度值为255,否则这些像素点被排除在物体区域之外,灰度值为0,表示背景或例外物体区域。 实现二值化有两种方法,一种是手动指定一个阈值,通过阈值进行二值化处理;另一种是自适应阈值二值化方法(OTSU算法和Kittle算法等。).使用第一种方法计算量小,速度快,但在处理不同图像时颜色分布差异很大;第二种方法适用性强,可以直接观察图像的轮廓,但计算比较复杂。本章的实验将使用第一种方法来实现图像的二值化。 如果特定物体内部有均匀一致的灰度值,并且处于其他灰度值的均匀背景下,则可以通过设定阈值获得更有效的分割效果。如果物体与背景的差异不在灰度值上(如纹理),则可以将差异特征转换为灰度差,然后使用阈值选择技术来分割图像。 53.2 实验任务 本节实验任务用于新起点开发板OV5640摄像头采集RGB将数据转化为565数据YCbCr格式,然后进行中值滤波,最后将灰度值二值化,通过HDMI显示。 53.3 硬件设计 本章节中硬件设计与“OV5640摄像头HDMI显示实验完全一样,这里就不赘述了。 53.4 程序设计 根据实验任务,设计如图 52.4.本章实验中显示的系统框架图延续了OV5640摄像头HDMI灰度显示实验的整体结构。本实验包括时钟模块、SDRAM控制器模块,IIC驱动模块、IIC配置模块、摄像头采集模块、图像处理模块和HDMI顶层模块。时钟模块,SDRAM控制器模块,IIC驱动模块、IIC配置模块、摄像头采集模块和HDMI这个实验没有修改顶层模块,OV5640摄像头HDMI图像处理模块已在显示实验中说明。 OV二值化实验系统框图如下图所示:
图 52.4.1 顶层系统框图 从上图可以看出,时钟模块(pll和pll_hdmi)为HDMI顶层模块、SDRAM控制模块和IIC驱动模块提供驱动时钟。IIC驱动模块和IIC配置模块控制传感器初始化的开始和结束。传感器初始化完成后,将收集到的数据写入摄像头采集模块。数据在摄像头采集模块处理后写入图像处理模块,图像处理模块处理后存储摄像头数据SDRAM控制模块。顶层模块从SDRAM在整个系统完成数据采集、缓存和显示之前,在控制模块中读取数据并驱动显示器显示。需要注意的是,图像数据采集模块在SDRAM在输出数据之前,传感器都是初始化的,避免了数据的输出SDRAM在初始化过程中将数据写入内部。 顶层模块代码如下:
1 module ov5640_hdmi_img_binarization( 2 input sys_clk , //系统时钟3 input sys_rst_n , ///系统复位,低电平有效4 ///摄像头 5 input cam_pclk , //cmos 数据像素时钟6 input cam_vsync , //cmos 场同步信号7 input cam_href , //cmos 行同步信号8 input [7:0] cam_data , //cmos 数据 9 output cam_rst_n , //cmos 复位信号,低电平有效10 output cam_pwdn , //cmos 电源休眠模式选择信号11 output cam_scl , //cmos SCCB_SCL线12 inout cam_sda , //cmos SCCB_SDA线13 //SDRAM 14 output sdram_clk , //SDRAM 时钟15 output sdram_cke , //SDRAM 时钟有效16 output sdram_cs_n , //SDRAM 片选17 output sdram_ras_n, //SDRAM 行有效18 output sdram_cas_n, //SDRAM 列有效19 output sdram_we_n , //SDRAM 写有效20 output [1:0] sdram_ba , //SDRAM Bank地址21 output [1:0] sdram_dqm , //SDRAM 数据掩码22 output [12:0] sdram_addr , //SDRAM 地址23 inout [15:0] sdram_data , //SDRAM 数据 24 //HDMI接口25 output tmds_clk_p, // TMDS 时钟通道26 output tmds_clk_n,27 output [2:0] tmds_data_p, // TMDS 数据通道28 output [2:0] tmds_data_n29 );30 31 //parameter define32 parameter SLAVE_ADDR = 7'h3c ; //OV5640的器件地址7'h3c33 parameter BIT_CTRL = 1'b1 ; //OV5640的字节地址为16位 0:8位 1:16位34 parameter CLK_FREQ = 27'd50_000_000 ; //i2c_dri模块的驱动时钟频率 35 parameter I2C_FREQ = 18'd250_000 ; //I2C的SCL时钟频率,不超过400KHz36 parameter V_CMOS_DISP = 11'd800 ; //CMOS分辨率--行37 parameter H_CMOS_DISP = 11'd1280 ; //CMOS分辨率--列 38 parameter TOTAL_H_PIXEL = 13'd2570 ; //CMOS分辨率--行39 parameter TOTAL_V_PIXEL = 13'd980 ;40 41 //wire define42 wire clk_100m ; //100mhz时钟,SDRAM操作时钟43 wire clk_100m_shift ; //100mhz时钟,SDRAM相位偏移时钟44 wire clk_50m ;45 wire hdmi_clk ; 46 wire hdmi_clk_5 ; 47 wire locked ;48 wire locked_hdmi ;49 wire rst_n ;50 wire sys_init_done ; //系统初始化完成(sdram初始化+摄像头初始化)51 wire i2c_exec ; //I2C触发执行信号52 wire [23:0] i2c_data ; //I2C要配置的地址与数据(高8位地址,低8位数据) 53 wire i2c_done ; //I2C寄存器配置完成信号54 wire i2c_dri_clk ; //I2C操作时钟55 wire [ 7:0] i2c_data_r ; //I2C读出的数据56 wire i2c_rh_wl ; //I2C读写控制信号57 wire cam_init_done ; //摄像头初始化完成 58 wire wr_en ; //sdram_ctrl模块写使能59 wire [15:0] wr_data ; //sdram_ctrl模块写数据60 wire rd_en ; //sdram_ctrl模块读使能61 wire [15:0] rd_data ; //sdram_ctrl模块读数据62 wire sdram_init_done ; //SDRAM初始化完成63 wire [10:0] pixel_xpos_w ; //HDMI横坐标64 wire [10:0] pixel_ypos_w ; //HDMI纵坐标65 wire post_frame_vsync ; //处理后的场信号66 wire post_frame_hsync ; //处理后的行信号67 wire post_frame_de ; //处理后的数据使能 68 wire [15:0] post_rgb ; //处理后的数据 69 70 //*****************************************************71 //** main code72 //*****************************************************73 74 assign rst_n = sys_rst_n & locked & locked_hdmi;75 //系统初始化完成:SDRAM和摄像头都初始化完成76 //避免了在SDRAM初始化过程中向里面写入数据77 assign sys_init_done = sdram_init_done & cam_init_done;78 //电源休眠模式选择 0:正常模式 1:电源休眠模式79 assign cam_pwdn = 1'b0;80 assign cam_rst_n = 1'b1;81 82 //锁相环83 pll u_pll(84 .areset (~sys_rst_n),85 .inclk0 (sys_clk), 86 .c0 (clk_100m),87 .c1 (clk_100m_shift), 88 .c2 (clk_50m), 89 .locked (locked)90 );91 92 pll_hdmi pll_hdmi_inst (93 .areset ( ~sys_rst_n ),94 .inclk0 ( sys_clk ),95 .c0 ( hdmi_clk ),//hdmi pixel clock 71Mhz96 .c1 ( hdmi_clk_5 ),//hdmi pixel clock*5 355Mhz97 .locked ( locked_hdmi )98 );99 100 //I2C配置模块101 i2c_ov5640_rgb565_cfg u_i2c_cfg(102 .clk (i2c_dri_clk),103 .rst_n (rst_n ),104 105 .i2c_exec (i2c_exec ),106 .i2c_data (i2c_data ),107 .i2c_rh_wl (i2c_rh_wl ), //I2C读写控制信号108 .i2c_done (i2c_done ), 109 .i2c_data_r (i2c_data_r ), 110 111 .cmos_h_pixel (H_CMOS_DISP ), //CMOS水平方向像素个数112 .cmos_v_pixel (V_CMOS_DISP ) , //CMOS垂直方向像素个数113 .total_h_pixel (TOTAL_H_PIXEL), //水平总像素大小114 .total_v_pixel (TOTAL_V_PIXEL), //垂直总像素大小115 116 .init_done (cam_init_done) 117 ); 118 119 //I2C驱动模块120 i2c_dri #(121 .SLAVE_ADDR (SLAVE_ADDR ), //参数传递122 .CLK_FREQ (CLK_FREQ ), 123 .I2C_FREQ (I2C_FREQ ) 124 )125 u_i2c_dr(126 .clk (clk_50m ),127 .rst_n (rst_n ),128 129 .i2c_exec (i2c_exec ), 130 .bit_ctrl (BIT_CTRL ), 131 .i2c_rh_wl (i2c_rh_wl ), //固定为0,只用到了IIC驱动的写操作 132 .i2c_addr (i2c_data[23:8]), 133 .i2c_data_w (i2c_data[7:0] ), 134 .i2c_data_r (i2c_data_r ), 135 .i2c_done (i2c_done ), 136 .scl (cam_scl ), 137 .sda (cam_sda ),138 .dri_clk (i2c_dri_clk ) //I2C操作时钟139 );140 141 //CMOS图像数据采集模块142 cmos_capture_data u_cmos_capture_data( //系统初始化完成之后再开始采集数据 143 .rst_n (rst_n & sys_init_done),144 145 .cam_pclk (cam_pclk ),146 .cam_vsync (cam_vsync),147 .cam_href (cam_href ),148 .cam_data (cam_data ), 149 150 .cmos_frame_vsync (cmos_frame_vsync),151 .cmos_frame_href (cmos_frame_href),152 .cmos_frame_valid (wr_en ), //数据有效使能信号153 .cmos_frame_data (wr_data ) //有效数据 154 );155 156 //图像处理模块157 vip u_vip(158 //module clock159 .clk (cam_pclk), // 时钟信号160 .rst_n (rst_n ), // 复位信号(低有效)161 //图像处理前的数据接口162 .pre_frame_vsync (cmos_frame_vsync ),163 .pre_frame_hsync (cmos_frame_href ),164 .pre_frame_de (wr_en ),165 .pre_rgb (wr_data),166 .xpos (pixel_xpos_w ),167 .ypos (pixel_ypos_w ),168 //图像处理后的数据接口169 .post_frame_vsync (post_frame_vsync ), // 场同步信号170 .post_frame_hsync ( ), // 行同步信号171 .post_frame_de (post_frame_de ), // 数据输入使能172 .post_rgb (post_rgb) // RGB565颜色数据173 174 ); 175 176 //SDRAM 控制器顶层模块,封装成FIFO接口177 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}178 sdram_top u_sdram_top(179 .ref_clk (clk_100m), //sdram 控制器参考时钟180 .out_clk (clk_100m_shift), //用于输出的相位偏移时钟181 .rst_n (rst_n), //系统复位182 183 //用户写端口 184 .wr_clk (cam_pclk), //写端口FIFO: 写时钟185 .wr_en (post_frame_de), //写端口FIFO: 写使能186 .wr_data (post_rgb), //写端口FIFO: 写数据 187 188 .wr_min_addr (24'd0), //写SDRAM的起始地址189 .wr_max_addr (V_CMOS_DISP*H_CMOS_DISP-1), //写SDRAM的结束地址190 .wr_len (10'd512), //写SDRAM时的数据突发长度191 .wr_load (~rst_n), //写端口复位: 复位写地址,清空写FIFO192 193 //用户读端口 194 .rd_clk (hdmi_clk), //读端口FIFO: 读时钟195 .rd_en (rd_en), //读端口FIFO: 读使能196 .rd_data (rd_data), //读端口FIFO: 读数据197 .rd_min_addr (24'd0), //读SDRAM的起始地址198 .rd_max_addr (V_CMOS_DISP*H_CMOS_DISP-1), //读SDRAM的结束地址199 .rd_len (10'd512), //从SDRAM中读数据时的突发长度200 .rd_load (~rst_n), //读端口复位: 复位读地址,清空读FIFO201 202 //用户控制端口 203 .sdram_read_valid (1'b1), //SDRAM 读使能204 .sdram_pingpang_en (1'b1), //SDRAM 乒乓操作使能205 .sdram_init_done (sdram_init_done), //SDRAM 初始化完成标志206 207 //SDRAM 芯片接口 208 .sdram_clk (sdram_clk), //SDRAM 芯片时钟209 .sdram_cke (sdram_cke), //SDRAM 时钟有效210 .sdram_cs_n (sdram_cs_n), //SDRAM 片选211 .sdram_ras_n (sdram_ras_n), //SDRAM 行有效212 .sdram_cas_n (sdram_cas_n), //SDRAM 列有效213 .sdram_we_n (sdram_we_n), //SDRAM 写有效214 .sdram_ba (sdram_ba), //SDRAM Bank地址215 .sdram_addr (sdram_addr), //SDRAM 行/列地址216 .sdram_data (sdram_data), //SDRAM 数据217 .sdram_dqm (sdram_dqm) //SDRAM 数据掩码218 );219 220 //例化HDMI顶层模块221 hdmi_top u_hdmi_top(222 .hdmi_clk (hdmi_clk ),223 .hdmi_clk_5 (hdmi_clk_5 ),224 .rst_n (rst_n ),225 226 .rd_data (rd_data ),227 .rd_en (rd_en ), 228 .h_disp (), 229 .v_disp (),230 .pixel_xpos (pixel_xpos_w),231 .pixel_ypos (pixel_ypos_w),232 .video_vs (), 233 .tmds_clk_p (tmds_clk_p ),234 .tmds_clk_n (tmds_clk_n ),235 .tmds_data_p (tmds_data_p),236 .tmds_data_n (tmds_data_n)237 ); 238 239 endmodule
FPGA顶层模块(ov5640_hdmi_img_binarization)例化了以下八个模块:时钟模块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显示实验”章节。 vip模块框图如下图所示:
图 52.4.2 vip模块框图 vip模块例化了RGB转YCbCr模块(rgb2ycbcr)、中值滤波模块(vip_gray_median_jilter)和二值化模块(binarization)。RGB转YCbCr模块负责将摄像头采集的RGB565格式数据到转换为YUV格式的数据。中值滤波模块负责将YUV格式的视频图像进行中值滤波后输出。二值化模块负责将中值滤波后的视频图像进行二值化处理再输出。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。 vip模块原理图如下图所示:
图 52.4.3 vip模块原理图 如上图所示,摄像头采集到16位rgb565输入vip模块,经过“rgb2ycbcr”模块转化为8位的yuv444数据,然后在将转化后的灰度数据(img_y)作为“vip_gray_median_filter”模块的输入,对灰度进行中值滤波处理,再将中值滤波后的数据输入进二值化模块,对数据进行二值化处理,最后输出经过二值化处理后的灰度数据“monoc”。 图像处理模块负责图像数据的格式转换,代码如下:
1 module vip(2 //module clock3 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 //wire define23 wire [ 7:0] img_y;24 wire [ 7:0] post_img_y;25 wire pe_frame_vsync;26 wire pe_frame_href;27 wire pe_frame_clken;28 wire ycbcr_vsync;29 wire ycbcr_hsync;30 wire ycbcr_de;31 wire monoc;32 33 //*****************************************************34 //** main code35 //*****************************************************36 37 assign post_rgb = {
16{
monoc}};38 39 //RGB转YCbCr模块40 rgb2ycbcr u_rgb2ycbcr(41 //module clock42 .clk (clk ), // 时钟信号43 .rst_n (rst_n ), // 复位信号(低有效)44 //图像处理前的数据接口45 .pre_frame_vsync (pre_frame_vsync), // vsync信号46 .pre_frame_hsync (pre_frame_hsync), // href信号47 .pre_frame_de (pre_frame_de ), // data enable信号48 .img_red (pre_rgb[15:11] ),49 .img_green (pre_rgb[10:5 ] ),50 .img_blue (pre_rgb[ 4:0 ] ),51 //图像处理后的数据接口52 .post_frame_vsync(pe_frame_vsync), // vsync信号53 .post_frame_hsync(pe_frame_href), // href信号54 .post_frame_de (pe_frame_clken), // data enable信号55 .img_y (img_y), //灰度数据56 .img_cb (),57 .img_cr ()58 );59 60 //灰度图中值滤波61 vip_gray_median_filter u_vip_gray_median_filter(62 .clk (clk), 63 .rst_n (rst_n), 64 65 //预处理图像数据66 .pe_frame_vsync (pe_frame_vsync), // vsync信号67 .pe_frame_href (pe_frame_href), // href信号68 .pe_frame_clken (pe_frame_clken), // data enable信号69 .pe_img_y (img_y), 70 71 //处理后的图像数据 72 .pos_frame_vsync (ycbcr_vsync), // vsync信号73 .pos_frame_href (ycbcr_hsync), // href信号74 .pos_frame_clken (ycbcr_de), // data enable信号75 .pos_img_y (post_img_y) //中值滤波后的灰度数据76 );77 78 //二值化模块79 binarization u_binarization(80 .clk (clk),81 .rst_n (rst_n),82 //图像处理前的数据接口 83 .ycbcr_vsync (ycbcr_vsync),84 .ycbcr_hsync (ycbcr_hsync),85 .ycbcr_de (ycbcr_de),86 .luminance (post_img_y),87 //图像处理后的数据接口 88 .post_vsync (post_frame_vsync),89 .post_hsync (post_frame_hsync),90 .post_de (post_frame_de),91 .monoc (monoc) //二值化后的数据92 );93 94 endmodule
代码的第37行表示对二值化后的1bit灰度数据进行位拼接,形成16bit的RGB565格式的数据输出。 代码的第40行至58行是对灰度转换模块的例化,在该模块以摄像头采集的16位RGB565红、绿、蓝三原色数据作为输入数据,通过算法实现RGB到YCbCr的转换,并输出8位灰度数据,并输出数据输出使能信号。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。 代码的第61行至76行是对中值滤波模块的例化,该模块负责将YUV格式的视频图像进行中值滤波后输出。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。 代码的第83行至96行是对二值化模块的例化,该模块主要是根据设定阈值,将图像化分为黑白两种颜色。 中值滤波模块和灰度转换模块在前面的章节已经讲解过,本次实验不在讲述。本次实验重点讲解二值化模块,下面是二值化模块的代码。
1 module binarization(2 //module clock3 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 define20 reg ycbcr_vsync_d;21 reg ycbcr_hsync_d;22 reg ycbcr_de_d ;23 24 //*****************************************************25 //** main code26 //*****************************************************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) begin34 if(!rst_n)35 monoc <= 1'b0;36 else if(luminance > 8'd64) //阈值37 monoc <= 1'b1;38 else39 monoc <= 1'b0;40 end41 42 //延时1拍以同步时钟信号43 always@(posedge clk or negedge rst_n) begin44 if(!rst_n) begin45 ycbcr_vsync_d <= 1'd0;46 ycbcr_hsync_d <= 1'd0;47 ycbcr_de_d <= 1'd0;48 end49 else begin50 ycbcr_vsync_d <= ycbcr_vsync;51 ycbcr_hsync_d <= ycbcr_hsync;52 ycbcr_de_d <= ycbcr_de ;53 end54 end55 56 endmodule
二值化的主要原理就是,给出一个设定的阈值,将灰度值与该阈值比较,若灰度值大于该阈值则monoc为1,若小于阈值,则monoc为0,如代码第33到40行。理论上阈值可以是0到255中的任意值,但阈值过大,会提取多余的部分;而阈值过小,又会丢失所需的部分,因此阈值选取就是一个很重要的步骤。 在代码第43到54行,通过寄存操作对gray_vsync、gray_clken等信号作了一个时钟周期的延迟。这是因为在进行二值判定时消耗了一个时钟,因此相应的同步信号也要延迟一个时钟周期,以实现与数据的同步。 53.5 下载验证 编译完工程之后就可以开始下载程序了。将OV5640摄像头模块插在新起点开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,下载完成后观察HDMI显示器显示的二值化后的图案。如下图所示:
图 52.5.1HDMI实时显示二值化图像