基于FPGA的车牌识别

Posted 旭旭宝宝和车友车行

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FPGA的车牌识别相关的知识,希望对你有一定的参考价值。

OV5640摄像头将采集到的数据通过摄像头驱动模块存入DDR3读写控制模块里,产生 DDR3burst写请求,通过总线转换程序,把 burst 写请求的信号转换成 *axi* *总线*请求,通过 axi 总线来访问 DDR3 的存储空间,将数据写入到DDR3中,模块中设计两个*异步FIFO*,向DDR3以*乒乓操作*读写数据。通过同样的方式,将读出的数据通过FIFO进入图像处理模块,首先RGB彩色图像经*色域提取算法*后转*灰度图像*,然后进行*二值化处理*,对二值图像进行*水平垂直投影**字符分割*,得到各个数字的水平和垂直边界,通过*M*N维的字符特征信息*统计后,传入*特征识别模块*进行特征匹配,从而识别图像中的数字,LCD 显示器显示处理后的二值化图像和图像的边界。

 

首先系统整体框图流程如图所示

1 首先采用的是ov5640摄像头模块,

外部控制器对 OV5640寄存器的配置参数是通过 SCCB 总线传输过去的,而 SCCB 总

线跟 I2C 十分类似。

SCCB 的起始信号、停止信号及数据有效性与 I2C 完全一样,见。

 起始信号: 在 SCL(图中为 SIO_C) 为高电平时, SDA(图中为 SIO_D)出现一

个下降沿,则 SCCB 开始传输。

 停止信号:在 SCL 为高电平时, SDA 出现一个上升沿,则 SCCB 停止传输。

 数据有效性:除了开始和停止状态, 在数据传输过程中,当 SCL 为高电平时,

必须保证 SDA 上的数据稳定,也就是说, SDA 上的电平变换只能发生在 SCL 为

低电平的时候,SDA 的信号在 SCL 为高电平时被采集。

OV5640 的寄存器

控制 OV5640 涉及到它很多的寄存器,可直接查询《ov5640datasheet》了解,通过这

些寄存器的配置,可以控制它输出图像的分辨率大小、图像格式及图像方向等。要注意的

是 OV5640 寄存器地址为 16 位。

若我们使用 Y2-Y9 数据线,图像格式设置为 RGB565,进行数据输出时, Y2-Y9 数据线会在 1 个像素同步时钟 PCLK 的驱动下发送 1 字节的数据信号,所以 2 个 PCLK 时钟可发送 1 个 RGB565 格式的像素数据。像素数据依次传输,每传输完一行数据时,行同步信号 HREF 会输出一个电平跳变信号,每传输完一帧图像时, VSYNC 会输出一个电平跳变信号。

cmos_write_req

模块通过判断摄像头的列同步信号 cmos_vsync 的上升沿,生成 ov5640 数据写入的请求信号,表示一帧图像开始写入请求。另外生成 write_addr_index 写地址选择和 read_addr_index 读地址选择,这里 read_addr_index 的值会比 write_addr_index 的值延迟一帧,使得读和写的地址不冲突,每传送完一帧,将index加一,更换地址,一共四个地址,类似于乒乓操作。 

cmos_8_16bit

cmos_8_16bit 模块完成摄像头输入的 2 个 8bit 数据转换到一个 16bit 数据(一个像素),数据位宽变成 2 倍,时钟频率不变,所以 16bit 数据是隔一个时钟周期有效,并不是每个时钟一直有效。

2数据传输模块

在模块‘frame_read_write’中使用到了 FIFO 的 IP core,通过两个 FIFO 分别作为 DDR3 控制器的读写接口,避免复杂的 DDR3 时序。因为时钟速率的不同,所使用的是异步时钟 FIFO。包含两个异步读写fifo,以及读写控制模块frame_fifo_write 、read。frame_fifo_write 模块完成 FIFO 数据到外部存储器的写入,因为 FIFO 接口是异步时钟 FIFO,可以完成写数据的跨时钟域转换。状态机转换图如下,收到写数据请求后进入应答状态“S_ACK”,如果写请求撤销,则进入检测 FIFO 空间大小状态“S_CHECK_FIFO”,检查 FIFO 内数据(fifo深度128)是否够一次突发写(128bit),如果有足够多的数据,进入突发写存储器状态“S_WRITE_BURST”,突发写完成后进入 “S_WRITE_BURST_END”状态。采用四个写地址模块,可以边写边读另一个模块。

frame_fifo_read 读模块完成从外部存储器读取数据,然后写到 FIFO,使用时钟异步 FIFO 可以完成数据从存储器时钟域到其他时钟域的转换。收到读请求以后进入应答状态“S_ACK”,等待读请求撤销后应答,进入 FIFO 深度检测状态 “S_CHECK_FIFO”,如果FIFO 空 间 足 够一 次突发读 , 进 入 突 发 读 状 态 “ S_READ_BURST ” , 突 发 读 结 束 后 进 入 “S_READ_BURST_END”。

在这里就是把摄像头采集的数据存 入写 FIFO 里,然后产生 DDR3 的 Burst 写请求,写入到 DDR3 中,另外读也是一样,当读 FIFO 里的数据小于一定值时,产生 DDR3 的 Burst 读请求。

3视频时序模块

本项目采用800*480的分辨率,七寸lcd屏幕

将数据打拍,包含彩条,彩条包含各个分辨率显示屏参数设置,输出行场同步信号,通过行计数器cnt_h对像素时钟计数,计满一个行扫描周期后清零并重新开始计数。程序第71至81行通过场计数器cnt_v对行进行计数,即扫描完一行后cnt_v加1,计满一个场扫描周期后清零并重新开始计数。 将行场计数器的值与VGA时序中的参数作比较,我们就可以判断行场同步信号何时处于低电平同步状态,以及何时输出RGB565格式的图像数据。

4 rgb-2gray模块 

先将rgb565转换成888,采用低位补零,把16位数据转化为24位

对于图像由彩色图转化为灰度图有三种方法分别为 加权法 均值法 最大值法 加权法就是 GRAY==0.3R+0.59G+0.11*B 均值法就是 GRAY==(R+G+B)/3,最大值发就是 max(R,G,B)

RR=(R-G)+(R-B) (G>R:R-G=0)(B>R:R-B=0) 2-1

GG= (G-R)+(G-B) (R>G:G-R=0)(B>G:G-B=0) 2-2

BB=(B-R)+(B-G) (R>B:B-R=0)(G>B:B-G=0) 2-3

R,G,B分别代表rgb图像的三个颜色通道,当颜色趋于红色时,RR通道趋于255(灰度白色);当颜色趋于绿色时,GG通道趋于255;当颜色趋于蓝色时,BB通道趋于255。

把dout24位数据的[7:0](蓝色部分)位给下一个模块, .i_gray(rgb2[7:0],rgb2[7:0],rgb2[7:0]),形成灰度图。

5 Threshold binary 图像二值化模块

图像二值化(Image Binarization)就是将图像上的像素点的灰度值设置为最大(白色)或最小(黑色), 也就是将整个图像呈现出明显的黑白效果的过程。把灰度图像二值化,得到二值化图像,这样有利于在对图像做进一步处理时,图像的集合性质只与像素值为 0 或 255 的点的位置有关,不再涉及像素的多级值,使处理变得简单

根据灰度阈值(85)的大小不同我们将图像大于阈值的部分变成白色(255),小于的部分变成黑色,阈值大小根据实验不断调试。蓝色车牌值应该大于阈值,变为白色,最后取反比为黑色,即白色背景黑色车牌。

方法:

OTSU算法(大津):它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。

对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:

对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:

ω0=N0/ M×N----------------------------------------------------

(1) ω1=N1/ M×N ----------------------------------------------------

(2) N0+N1=M×N----------------------------------------------------

(3) ω0+ω1=1 --------------------------------------------------------

(4) μ=ω0μ0+ω1μ1------------------------------------------------

(5) g=ω0(μ0-μ)^2+ω1(μ1-μ)^2-----------------------------------

(6) 将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2----------------

(7) 采用遍历的方法得到使类间方差最大的阈值T,即为所求。

6 HVcount 行场计数模块

图像行列计数,为了之后的边界查找

hcount:使能信号每拉高一次记一次数。

vcount:行数每达到一帧计数加一。

7水平垂直投影法

图像对应方向的投影,就是在该方向取一条直线,统计垂直于该直线(轴)的图像上的像素的黑点数量,累加求和作为该轴该位置的值;基于图像投影的切割就是将图像映射成这种特征后,基于这种特征判定图像的切割位置(坐标),用这个坐标来切割原图像,得到目标图像。模块可在网上找到参考。

使用状态机对数据跳变进行记录,记录跳变所有坐标及边界。

例如白纸黑字,对像素信号低电平(黑色)进行统计,把此时横纵坐标写到对应ram中,方便计算边界。

 8   capture_lpr

 把选中车牌部分像素翻转,其他部分变黑

9。vp8 

完成目标字符的边界计算,采用水平和垂直投影算法。原理和projection类似

利用水平和垂直投影完成字符分割程序:


 

 

10 recognition

第一步:首先找到字符上下左右边界。

第二步:分成MXN维,分成八行五列。

第三步:统计特征信息。

lpr_recognition:top模块,将子模块中获得的char字符信息给char1、、、char8,采用状态机,分为四次,每次生成两个字符。

capture_single:与capture功能类似,显示区域的图像,其他地方为白

character_recognition:调用子模块area统计一个区域内的黑色像素点数,分别统计八列,一列有五行。然后将每一块的像素数与每一块面积一半进行比较,大于则为1,将此作为数字特征信息,将总共四十个字符信息用拼接方法拼成一个40位char字符。

11 char_match

调用char模块,获得车牌每一个字符相匹配的城市字母数字。

char模块:共三个部分,第一部分:先将上一模块获得的特征信息(40位)与调用的模板字符相同或,即相同为1,使用score函数将每一位相加,得到score,多少个城市就有多少个score。第二部分:使用MUX function,用于比较被测字符与模板字符相似程度,score越大,越相似,最大的就是相应的模板字符。第三部分:输出,将最相似的字符如城市以首字母输出到下一个模块。

12

lut_ov5640_rgb565_800_480

摄像头配置模块,提供8位i2c地址8'h78(8’b01111000),寄存器地址,寄存器数据

13 DDR3模块

此模块为本工程的最重要的部分,因此可以在本站搜索ddr3 fpga的读写来更胜层次的理解。

DDR3是一种内存规格,它是SDRAM家族的内存产品。DDR3之前的产品有DDR和DDR2。DDR(Double Data Rate)是双倍速率同步动态随机存储器,严格的说DDR应该叫DDR SDRAM。DDR2是DDR产品的升级产品,它是四倍速率同步动态随机存储器。DDR3在DDR2的基础上实县了更高的性能(增加到八倍)和更低的电压。
DDR内部结构框图如下所示:

如上图所示:

标号1:逻辑控制单元,用于输入命令解析和模式控制等。
标号2:行地址选通单元。
标号3:内部存储阵列,上图中分为8个bank。
标号4:bank控制逻辑单元。
标号5:IO锁存和DM标记单元,用于刷新和预充电。
标号6:数据读写驱动接口。
标号7:列地址选择单元。
在7系列FPGA芯片中,Xilinx 为用户提供了一个 DDR 控制的 IP核,称为MIG IP 控制器。这样用户可以很方便的通过 MIG 控制器读写 DDR 存储器。7 系列的 DDR 控制器的解决方案如下所示:

如上图所示,DDR3 控制器包含 3 部分:

用户接口模块(User interface Block);
存储器控制模块(Memory Controller);
DDR3 的物理接口(Physical Layer)。
在vivado中创建DDR3的MIG控制器,步骤可以参考网上教程。

采用野火的ddr3驱动控制,含有乒乓操作,与代码中frame_read_write 和总线请求一致

由 4 个 模 块 构 成 : AXI4 主 机 控 制 模 块 axi_ctrl , AXI4 主 机 写 数 据 模 块axi_master_write,AXI4 主机读数据模块 axi_master_read,Xilix 官方 AXI4 接口的 migIp 核axi_ddr。 

AXI4 写模块将复杂的 AXI4 接口的写接口进行封装成建议的用户接口,用户接口包括fifo 端数据接口与若干控制信号。AXI4 写接口包括写通道的写地址通道,写通道写数据通道,写通道写响应通道这三个接口,其中每组最重要的还是握手信号接口,也就是主机控制的 valid 有效信号与从机控制的 ready 准备就绪信号。通俗来讲,主机发出 valid 告诉从机本数据有效,从机接收到 valid 发送 ready 告诉主机,准备已经就绪,就这样主机与从机完成了一个握手信号。

AXI4 读写控制模块的主要功能是:使用 fifo 对传入的待写入 DDR3 SDSAM 的数据和从 DDR3 SDRAM 读出的数据进行缓存,实现跨时钟域处理;为数据读写 AXI 读写主机提供读写地址。

 14   为什么要用sdram。

由于摄像头产生的数据时钟速率和显示屏的时钟不匹配,而且当摄像头传来数据时,显示屏驱动模块不一定在此时需要数据,况且同一时刻摄像头传进的像素的位置不一定就是显示屏正刷新到的位置。故不能将摄像头的数据直接直接传输到显示屏驱动模块。

一张24bit的的全彩图的,每个像素点占据3byte的空间,常见的不同尺寸的图片一帧所占空间如下:

108019203byte=6,220,800byte=5,9mbyte;

9604803byte=1,382,400byte=1.3mbyte

4802723byte=391,680byte=0.3mbyte

通常板载的sdram的大小有16MB,32MB,64MB,128MB,等等,由设计成本决定,但用于储存一帧图片绰绰有余。

只有将图像数据临时储存起来,这样读写便互不所影响。当摄像头传来有效数据时,便将数据存入sdram,当显示屏需要数据时,便从sdram中读取数据,发送给显示屏用于显示。这样便可以将读写储存隔离。

低成本的板载sdram的时钟频率也在100MHz以上,数据宽度为16bit,数据带宽最小为100M2byte(16bit)=200Mbyte/s。按60HZ,640480的图片计算,一帧图片要进行读和写两次操作,通常由摄像头传入的图像为16位宽,那么图像传输的速率为:640 * 480 * 2btye(16bit) * 2 * 60 = 70Mbyte,可见sdram的带宽足够,满足图像实时显示要求。

2,为什么要用fifo做数据的临时缓存?

为什么不能将数据直接存入sdram,还要经过fifo临时缓存呢?一是由于跨时钟域。摄像头产生的数据的速率和sdram的写入时钟速率不匹配。一般而言,sdram的时钟频率都要大于像素时钟的一到两倍。故需要一个读写双时钟的fifo。将像素时钟接入到fifo的写时钟端口,像素数据有效信号接入到fifo的写使能端口,将有效的数据写入到fifo中。将sdram的时钟接到fifo的读时钟端口,用于从fifo中读取数据。

二是由于sdram的突发传输,要保证连续突发传输时每一个数据都是有效数据。如果直接将摄像头的数据传输到sdram端口 ,在连续传输的128个字节中,像素数据不一定是全部连续有效的数据。只将有效数据储存进fifo中后,从fifo中读出的连续数据一定都是连续的有效数据。

对于读fifo,也是同理,显示屏的驱动时钟和sdram的时钟也存在跨时钟域,而且在突发读取时,也不能保证从sdram中传出的数据正好和显示所需要Dev数据相匹配。故需要有一个双时钟端口的用于读数据的fifo做数据的临时缓存。

3,何时将fifo中的数据写入sdram?

sdram的突发长度设置为128,设置当写fifo中的数据量大于128时,进行一次写突发传输,将fifo中的128个数据搬移到sdram中。图像数据不断从摄像头传入,写进fifo中,每当写入的数据大于预设Dev值,就进行一次写突发传输。这个由读写仲裁模块所控制。

4,何时将sdram中的数据

显示屏驱动模块要从读fifo中读取数据,设置一个阈值,当读fifo中的数据小于该阈时,便进行一次突发传输,将数据从sdram中临时缓存到fifo中,用于显示驱动的读操作。

5,何为乒乓操作,为何要乒乓操作

乒乓操作的具体方法为,在sdram中设置两个储存空间,用于储存两张图片。分别用于储存摄像头传来的图像数据,和显示屏读取数据。一帧图片传输完成后,读写区域互换。这样能保证在显示屏显示时,能够显示一张完整的图像。如果利用同一片储存区域来储存图像,当前一帧图像还没有读取显示完成,下一帧图像的数据就将该区域覆盖,那么显示屏上的画面会出现拖影现象,两帧图像会交叠在一起。

15 还可以添加send_char模块 字符提取之后可以用rs232将字符发送出去,波特率自己设定。

最后达到的效果如图所示​​​​​​​

。最后留言一段 车牌识别的FPGA 实现本质上要好好学会sdram控制 板子采用xilinx7系列芯片做 准确率很高 如果板子不同的话 可以自己将程序对应的管教修改即可,必须得用带有ddr3的板子才能实现。开发工具采用vivado2019,如果有想要拿来做课设或者毕业设计的可以联系我v loser1980173994,价格不高,能在你接受的程度。

 

以上是关于基于FPGA的车牌识别的主要内容,如果未能解决你的问题,请参考以下文章

SoC FPGA加accsytem加神经网络算子实现: 车牌识别BMP版本

基于AndroidiOS平台的移动端车牌识别技术及实现车牌识别过程

深度学习实践基于深度学习的车牌识别(python,车牌检测+车牌识别)

车牌识别基于matlab投影模板匹配车牌识别含Matlab源码 1359期

车牌识别基于matlab投影模板匹配车牌识别含Matlab源码 1359期

车牌识别-车牌定位