数字是人们日常生活中进行信息交流时不可缺少的信息载体,面对大量的数字如何让机器识别处理,包括身份证号识别、车牌号识别等就成为了一个研究点,同时,数字识别必然涉及到图像处理,本章我们通过数字特征识别入手对数字识别有一个基本的了解,以及对数字图像处理有一个基本的认识。 本章包括以下几个部分: 53.1 简介 53.2 实验任务 53.3 硬件设计 53.4 程序设计 53.5 下载验证
54.1 简介 数字识别一般通过特征匹配及特征判别的方法来进行处理,前者一般适用于规范化的印刷体字符识别,现今该技术基本成熟,后者多用于手写字符识别,其研究还处于探索阶段,识别率还比较低。本章我们通过对印刷体数字识别入手,了解特征匹配识别的应用。 数字特征识别是通过对数字的形状以及结构等几何特征进行分析与统计,通过对数字特征的匹配从而达到对图像中数字的识别,如下图所示:
图 54.1.1 数字几何特征 x1、x2是水平方向的两条直线,与数字长度成特定比例关系,y是竖直方向的直线,占数字宽度一半,这三条线与数字的交点可以得到数字的特征值。下面以数字0为例,如下图所示:
图 54.1.2 数字0的几何特征 红框是数字的边界,x1取上下边界的2/5处,x2取上下边界的2/3处,y取左右边界的1/2,可以看到x1与数字0有两个交点,左右(以y为分界)各一个,x2同样与数字0有两个交点,左右各一个,y与数字0有两个交点。以此统计数字特征实现识别,如下表所示: 表 54.1.1 数字特征表 54.2 实验任务 本节实验任务是使用新起点开发板实现数字识别,利用RGB屏(支持目前正点原子推出的所有RGB-LCD屏)显示OV5640摄像头捕获到的数字,并将识别到的数字显示在数码管上。 54.3 硬件设计 本章节中硬件设计前面的章节已经讲解过,此处不再赘述。 54.4 程序设计 根据实验任务,首先设计如图 54.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头RGB-LCD灰度显示实验”的整体架构。时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、图像尺寸配置模块、数码管显示模块、摄像头采集模块、图像处理模块和LCD顶层模块。其中时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、摄像头采集模块和图像尺寸配置模块本次实验没有做任何修改,这些模块在“OV5640摄像头LCD显示实验”中已经说明过,这里不再详述,本次实验只对图像处理模块和LCD顶层模块进行了修改。 OV5640摄像头的数字识别实验框图如下图所示:
图 54.4.1 顶层系统框图 由上图可知,OV5640摄像头采集到的数据通过摄像头驱动模块写入SDRAM,然后通过SDRAM控制器模块读出,读出的数据在LCD顶层模块的驱动下进入vip模块,在vip模块内部图像数据先由rgb2ycbcr模块将RGB转化为YCbCr,然后进行二值化处理,得到二值图像,对二值图像进行水平垂直投影即图像分割,得到各个数字的水平和垂直边界,将数字边界信息送入特征识别模块进行特征匹配,从而识别图像中的数字,将识别到的数字再送入LCD顶层模块,最后在LCD屏的左上端显示。 了解了整个处理流程后,我们来看一下底层硬件中各个模块的设计思路。由于除vip模块之外的模块都在先前的实验中介绍过,这里就不多做介绍。 vip模块是封装层模块,是对图像处理子模块的顶层封装,其内部模块如下图所示:
图 54.4.2 vip模块的子模块 rgb2ycbcr是RGB转YCbCr模块、binarization是二值化模块、projection是投影分割模块、 digital recognition是特征匹配识别模块。 下面是vip模块的原理图。
图 54.4.3 vip模块原理图 vip模块的输入端有帧数据使能信号pre_frame_de、帧行同步信号pre_frame_hsync、帧场同步信号pre_frame_vsync、坐标信号xpos和ypos和像素pre_rgb,这些信号由LCD驱动模块输入。vip模块的输出端除了vip模块处理后的帧数据使能信号post_frame_de、帧行同步信号post_frame_hsync、帧场同步信号post_frame_vsync外,还有一个识别后的数字信号digit。由于新起点开发板板载6位数码管,每位数码管用8421BCD编码显示,总共需要4*6=24位,即digit信号位宽为24位,该信号输出给数码管驱动模块在数码管上显示识别到的数字。 vip模块有三个参数,如下图所示:
图 54.4.4 vip模块的参数 NUM_ROW和NUM_COL分别指需识别的数字的行数和列数,这里我们指定识别1行4列的数字; DEPBIT是数据的位宽,主要用于确定数字边界大小的位宽,与水平和垂直像素大小有关。 vip模块中RGB转YCbCr模块和二值化模块在前面实验已经讲解过,这里不再讲述。下面是投影分割模块的代码。
1 module projection #(
2 parameter NUM_ROW = 1 ,
3 parameter NUM_COL = 4 ,
4 parameter H_PIXEL = 1280,
5 parameter V_PIXEL = 800 ,
6 parameter DEPBIT = 12
7 )(
8 //module clock
9 input clk , // 时钟信号
10 input rst_n , // 复位信号(低有效)
11
12 //Image data interface
13 input frame_vsync , // vsync信号
14 input frame_hsync , // hsync信号
15 input frame_de , // data enable信号
16 input monoc , // 单色图像像素数据
17 input [10:0] xpos ,
18 input [10:0] ypos ,
19
20 //project border ram interface
21 input [DEPBIT-1:0] row_border_addr_rd,
22 output [DEPBIT-1:0] row_border_data_rd,
23 input [DEPBIT-1:0] col_border_addr_rd,
24 output [DEPBIT-1:0] col_border_data_rd,
25
26 //user interface
27 input [10:0] h_total_pexel ,
28 input [10:0] v_total_pexel ,
29 output reg [ 3:0] num_col , // 采集到的数字列数
30 output reg [ 3:0] num_row , // 采集到的数字行数
31 output reg [ 1:0] frame_cnt , // 当前帧
32 output reg project_done_flag // 投影完成标志
33 );
34
35 //localparam define
36 localparam st_init = 2'b00;
37 localparam st_project = 2'b01;
38 localparam st_process = 2'b10;
39
40 //reg define
41 reg [ 1:0] cur_state ;
42 reg [ 1:0] nxt_state ;
43 reg [12:0] cnt ; //数据使能计数器
44 reg h_we ; //列ram写使能
45 reg [12:0] h_waddr ; //列ram写地址
46 reg [12:0] h_raddr ; //列ram读地址
47 reg h_di ; //列ram写数据
48 reg h_do_d0 ;
49 reg v_we ; //行ram写使能
50 reg [12:0] v_waddr ; //行ram写地址
51 reg [12:0] v_raddr ; //行ram读地址
52 reg v_di ; //行ram写数据
53 reg v_do_d0 ;
54 reg frame_vsync_d0 ;
55 reg [DEPBIT-1:0] col_border_addr_wr; //列边界ram写地址
56 reg [DEPBIT-1:0] col_border_data_wr; //列边界ram写数据
57 reg col_border_ram_we ; //列边界ram写使能
58 reg [DEPBIT-1:0] row_border_addr_wr; //行边界ram写地址
59 reg [DEPBIT-1:0] row_border_data_wr; //行边界ram写数据
60 reg row_border_ram_we ; //行边界ram写使能
61 reg [3:0] num_col_t ; //一行待测数字个数
62 reg [3:0] num_row_t ; //一列待测个数
63
64 //wire define
65 wire frame_vsync_fall ;
66 wire h_do ; //列ram读数据
67 wire v_do ; //行ram读数据
68 wire h_rise ;
69 wire h_fall ;
70 wire v_rise ;
71 wire v_fall ;
72
73 //*****************************************************
74 //** main code
75 //*****************************************************
76
77 //列数据跳变的上升沿
78 assign h_rise = h_do & ~h_do_d0;
79 //列数据跳变的下降沿
80 assign h_fall = ~h_do & h_do_d0;
81 //行数据跳变的上升沿
82 assign v_rise = v_do & ~v_do_d0;
83 //行数据跳变的下降沿
84 assign v_fall = ~v_do & v_do_d0;
85 //场信号的下降沿
86 assign frame_vsync_fall = frame_vsync_d0 & ~frame_vsync;
87
88 //投影结束后输出采集到的行列数
89 always @(*) begin
90 if(project_done_flag && cur_state == st_process)begin
91 num_col = num_col_t;
92 num_row = num_row_t;
93 end
94 else begin
95 num_col = num_col;
96 num_row = num_row;
97 end
98 end
99
100 //打拍采沿
101 always @(posedge clk or negedge rst_n) begin
102 if(!rst_n) begin
103 h_do_d0
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?