物联网毕业设计 STM32车牌识别系统 - 嵌入式


1 简介

Hi,大家好,学长今天向大家介绍一个 单片机项目

基于stm32的车牌识别系统设计

大家可用于 课程设计 或 毕业设计

选题指导,项目分享:

https://gitee.com/yaa-dc/warehouse-1/blob/master/iot/README.md

在这里插入图片描述

2 项目课题背景

在我们的日常生活中, 接触到了很多关于电子科技的技术。 在电子科技交通领域中, 有很多技术都在无形中加入我们的生活, 如图像处理技术, 自动检测技术等。对于道路交通应用到的技术, 车牌识别系统是交通管理的主要技术。 一套完整的车牌识别系统, 可以给我们的日常生活带来规范, 从而能够使交通事故更少的发生,给我们的出行带来顺畅, 给我们的日常生活带来方便。 所以车牌识别系统目前是一个交通管理必备的技术, 因此本文对车牌识别系统进行了研究与实现。

3 应用场景

车牌识别系统的应用前景很广泛, 用法也简单可靠。 它不但用于道路交通监控,而且也用于小区和停车场方面的管理、 收费站管理系统、 车流统计、 车牌验证和移动车载系统等方面。

3.1 小区和停车场方面的管理

小区和停车场车牌识别管理系统是对出入车辆的监控。 进出的车辆会被车牌系统识别, 并通过网络传输, 识别出来的车牌信息发送到管理系统中登记, 这样的流程不仅节省了人力保证了人员的安全, 也节约了进出登记时间, 大大提升了效率

3.2 交通道路的监控

在道路交通的检测部门中, 每天都会出现大量的违规车辆。 对于那些列进“黑名册” 中的车辆, 比如那些肇事过后逃逸的车辆、 那些已经挂失过的车辆和那些欠费过的汽车等, 我们通常可以将这些车的车牌用摄像机录制成视频记录下来。 如果通过人工识别并比较车牌号码, 这样会导致工作的效率会比较低, 而且容易出现错误; 如果应用车牌识别系统, 给定一个车牌追踪目标, 系统就会对摄像头监控下的车辆信息进行自动扫描。 对于车牌号码识别之后做比较并处理, 如果符合条件就立刻报警。

3.3 收费站管理系统

我国在 2019 年推出高速公路全面实行 ETC 交费, 车辆进出收费站, 不管是桥梁, 或是高速公路, 隧道等地方, 对于车牌识别系统的要求相对比较严格。 车牌识别系统可以大大减少平常收费系统工作量较大和人工容易产生疲劳等等的不足, 也可以减少劳动的强度, 节省了大量物力和人力。 同时, 对于 ETC 收费系统还能够节省司机的大量开车时间。 因此在收费站, 车牌识别系统是一种高效率、 高质量的东西, 可以提高生活物质水平。

3.4 车流统计、 车牌验证和移动车载系统

车牌识别系统可以用于对车辆流量统计。 当交通路道处于比较复杂的路段, 出现塞车或者车辆处于超速状态时, 系统会根据捕获到的车辆信息记录发送到服务端,服务端再发送到对应车牌车主绑定的客户端。 所以车牌识别的问题已经成为了交通工程领域中重点研究课题之一。

4 系统设计方案

4.1 硬件方案

学长设计的系统由三个部分组成: 图像采集、 处理和显示装置。 本文采用基于ARM cortex-m3 内核的 STM32F103 芯片作为设计平台, 它具有较高的处理能力, 可以进行比较复杂的计算, 基本上可以满足设计需要。 图像采集用 OV7670 摄像头。而显示装置是用 TFT_ILI9341 2.8 寸显示屏。 系统模块框图如图 所示。

在这里插入图片描述

4.2 软件实现流程

车牌区域识别、 字符分割两者均采用根据跳变点划线的方式来对字符的边界以及车牌区域进行确定。 摄像头采集到图像后进行扫描测试, 获取摄像头像素的值,再根据屏幕纵向 240 方向跳变点的显示点数, 分析跳变点; 而车牌测定就根据屏幕横向 320 方向跳变点的显示进行分析。 两个方向分析完毕后, 就会对字符进行分割,分割后就可以进行字符的识别。

在这里插入图片描述

5 硬件系统设计

5.1 主控STM32

STM32 核心板的 5V 引脚接着供电引脚, 系统的供电为 DC5V。 通过稳压芯片,在 STM32 核心板上将 5V 的供电电压转换为 3.3V 电压。 3.3V 电压在 STM32 核心板的引脚输出。 3.3V 作为供电电压被 STM32 芯片、 OV7670 摄像头和 TFT 液晶屏幕引用。

在这里插入图片描述

5.2 摄像头

在系统适配度、 性能和性价比上经过对比后, 系统采用 OV7670摄像头。 OV7670摄像头功耗低, 可以与本系统的其他硬件搭配; 在性能上, 摄像头自带影像处理器和具备 VGA 摄像头的操作功能。 并且具备的传感器技术, 是摄像头的亮点, 它可以完善甚至可以完全修复如托尾、 浮散等光学以及电子缺陷。

在这里插入图片描述

5.3 显示屏

学长要想将采集到的车牌图像信息以及识别结果得以显示, 系统就必须有显示部分。系统的使用 2. 8 寸的 TFT 显示屏作为显示模块。 显示屏默认 8 位的数据长度, 同时它支持 16 位长度的数据, 只要将一个 0 欧电阻连接在 R11 引脚, 就可以使用 16位。 显示屏还支持 240*320 像素的 RGB565 格式。

在这里插入图片描述

6 软件设计

车牌识别主要通过将采集到的数据进行拍照定位、字符分割及识别等技术得到,具体流程图如图。

在这里插入图片描述

6.1 车牌定位

首先对采集到的图像进行大范围搜索,找到符合的区域座位后选取,然后对其进行进一步判断,最终选定最佳的区域分隔出来,具体流程如图。

在这里插入图片描述

车牌区域出现了约 15 个以上的跳变点, 是通过二值化分析后呈现出来的。 根据跳变点的波动分析, 可以确定车牌区域的位置。
在这里插入图片描述
关键代码

void ChangePoint_Show_240() ; //240 方向跳变点显示
{
for(a=0; a<240; a++) { //显示对应的横向跳变点
//跳变点显示, 红色标记
LCD_DrawPoint(TableChangePoint_240[a], a, 0xf800) ;
//跳变点个数(阈值) 设定
if(TableChangePoint_240[a]>=15) {
//显示达到阈值标准的点
for(b=35; b<40; b++) {
LCD_DrawPoint(b, a, 0x6666) ; //Green
}
}
16
}
}
for(a=0; a<240; a++) { //建立参考线 10、 20、 30
LCD_DrawPoint(a, Min_ChangePoint_240, 0x001f) ;
LCD_DrawPoint(10, a, 0x63<<5) ; //10
LCD_DrawPoint(20, a, 0x63<<5) ; //20
LCD_DrawPoint(30, a, 0x63<<5) ; //30
}
void ChangePoint_Analysis_240() { //240 跳变点分析
Min_ChangePoint_240=240;
Max_ChangePoint_240=0;
for(a=0; a<240; a++) //240 扫描, 获取上下限值:
Min_ChangePoint_240,
Max_ChangePoint_240
{
while(TableChangePoint_240[a]<=15) //阈值调节
{
a++;
}
Min_ChangePoint_240=a;
while(TableChangePoint_240[a]>15) //阈值调节
{
a++;
}
Max_ChangePoint_240=a;
if(Max_ChangePoint_240-Min_ChangePoint_240>=15)
{
a=240; //连续性
}
//向上微调 3 像素
Min_ChangePoint_240=Min_ChangePoint_240-3;
//向下微调 2 像素
Max_ChangePoint_240=Max_ChangePoint_240+2;
for(a=30; a<280; a++) //显示上界限
{
LCD_DrawPoint(a, Max_ChangePoint_240, 0x001f) ;
}
for(a=30; a<280; a++) //显示下界限
{
//显示 50, 参考 50 像素位置处, 车牌位置不要超过这根线, 免得不能字符的
归一化处理
for(a=30; a<280; a++)
{
LCD_DrawPoint(a, Min_ChangePoint_240+50, 0xf800) ;
}
flag_MaxMinCompare=1;
//判断合法性 1: 最小值>最大值
if(Min_ChangePoint_240>Max_ChangePoint_240)
{
flag_MaxMinCompare=0;
}
//判断合法性 2:
if(Min_ChangePoint_240==240| | Max_ChangePoint_240==0)
{
flag_MaxMinCompare=0;
}
//判断合法性 3:
if(Max_ChangePoint_240-Min_ChangePoint_240<15)
{
flag_MaxMinCompare=0;
}

}

6.2 字符分割

对检测得到的车牌进行切割,从而达到将每一位字符分隔开并为下一步做铺垫。具体流程如图。

在这里插入图片描述

在这里插入图片描述

车牌的整体长度为 44cm, 宽度为 14cm。 不计第 2、 3 个字符中间的小圆点, 车牌上共有 7 个字符, 均为规则的印刷体字。 除了军车、 警车、 教练车、 领事馆车外,标准的民用车辆牌照均为 7 个字符。

车牌首位为省名简称, 是一个汉字, 如粤、 苏、 辽等。 次位为英文字母, 接下来为英文字母或阿拉伯数字。 其中每个字符统一宽度为 4. 5cm, 高 9cm, 第二、 三个字符间间距为 3.4cm, 中间小圆点 1cm 宽, 小圆点与第 2、 3 个字符间间距分别为1.2cm, 其余字符间间距为 1.2cm。

如果分析后根据边沿, 里面的字符数为整个车牌, 也就是 8 个完整的字符, 则会更加精确切割出每个字符位置。 在处理过程中, 获取每个字符的左边界 KL 和右边界 K R 。 如下图所示, 垂直蓝线是每个文字的边界标记。 字符分割, 为下一个字符匹配准备通用参数。

6.3 字符识别

字符分割后, 进行归一化处理, 逐个字符进行匹配。 程序中的字符模板由模板提取软件提取, 模板大小为 24*50 的单一像素。 逐个字符进行匹配, 以相似度值最大的对应字符作为输出结果并显示。

关键代码

Stm32_Clock_Init(16) ; //初始化时钟
Data_LCD_ColorChange() ; //车牌测定
u8 MoShiShiBie_All(u8 begin, u8 end) //字符匹配, 模式识别, 选择性匹配
{
u16 Compare_num, num_save;
u8 a, b, e, a_save, st1, st2, s1, s2;
int num1;
for(a=begin; a<end; a++)//36
{
num1=0;
for(b=0; b<150; b++)
{
st1=table_picture[b];
st2=Table[150*a+b];
for(e=0; e<8; e++)
{
s1=st1&(1<<e) ;
s2=st2&(1<<e) ;
if(s1==s2) num1++;
}
}
}
}

7 实物测试

在这里插入图片描述

显示屏会显示实时的步骤。 通电后, 屏幕首先会初始化, 会出现绿色和红色两个界面; 第二会根据传输到屏幕上图像, 显示屏有 20 秒的处理时间进行二值化分析出车牌区域; 第三, 显示屏图像静止, 对车牌进行切割处理; 第四把每个切割后的字符与取模的标准车牌模型进行比较, 把相似度最高的字符输出; 最后把车牌结果输出到结果界面。

在这里插入图片描述
外场测试
在这里插入图片描述

在这里插入图片描述

8 部分关键代码

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "tftlcd.h"
#include "key.h"
#include "malloc.h" 
#include "sd.h"
#include "flash.h"
#include "ff.h" 
#include "fatfs_app.h"
#include "exti.h"
#include "time.h"  
#include "ov7670.h"
#include "bmp.h"

#include "esp8266_drive.h"

extern u8 ov_sta;	//在exit.c里面定义
extern u8 ov_frame;	//在time.c里面定义

//更新LCD显示
void camera_refresh(void)
{
	u32 i,j;
 	u16 color;
	
	if(ov_sta)//有帧中断更新
	{
		LCD_Display_Dir(1);
		
		LCD_Set_Window(0,(tftlcd_data.height-240)/2,320-1,240-1);//将显示区域设置到屏幕中央
		OV7670_RRST=0;				//开始复位读指针 
		OV7670_RCK_L;					//设置读数据时钟为低电平	
		OV7670_RCK_H;
		OV7670_RCK_L;
		OV7670_RRST=1;				//复位读指针结束 
		OV7670_RCK_H;
		
		for(j=76800;j>0;j--)//较快方式
		{
			OV7670_RCK_L;
			color=GPIOF->IDR&0XFF;	//读数据
			OV7670_RCK_H; 
			color<<=8;  
			OV7670_RCK_L;
			color|=GPIOF->IDR&0XFF;	//读数据
			OV7670_RCK_H; 
			
			LCD_WriteData_Color(color);	//显示图片
			
		}
	}
		
			ov_sta=0;					//清零帧中断标记
			ov_frame++; 
			LCD_Display_Dir(0);
}

int main()
{
	u8 i=0;
	u8 sbuf[15];
	u8 count;
	u8 res;
	u8 sd_ok;
	u8 *pname;				//带路径的文件名 
	u8 key;
	u8 *lp;  //存储车牌
	
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	LED_Init();
	USART1_Init(9600);
	
	ESP8266_Init(115200);
	ESP8266_STA_LinkAP();
	
	TFTLCD_Init();			//LCD初始化
	KEY_Init();
	
	EN25QXX_Init();				//初始化EN25Q128	  
	my_mem_init(SRAMIN);		//初始化内部内存池
	
	while(OV7670_Init())//初始化OV7670
	{
		LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,24,"OV7670 ERROR!");
		delay_ms(200);
		LCD_Fill(10,10,239,206,WHITE);
		delay_ms(200);
	}
 	LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,24,"OV7670 OK!");
	delay_ms(1500);	
	
  	
	while(FATFS_Init()){
		LCD_ShowString(10,40,tftlcd_data.width,tftlcd_data.height,24,"FATFS ERROR!");
		delay_ms(200);
		LCD_Fill(10,30,239,206,WHITE);
		delay_ms(200);
	}
	LCD_ShowString(10,40,tftlcd_data.width,tftlcd_data.height,24,"FATFS OK!");
	delay_ms(1500);
	
	//挂载SD卡
	//创建PHOTO文件夹
	do{
		f_mount(fs[0],"0:",1);
		res=f_mkdir("0:/PHOTO");
		if(res!=FR_EXIST&&res!=FR_OK) 	//发生了错误
		{		    
			LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,24,"SD ERROR!");
			delay_ms(200);				  
			LCD_ShowString(10,100,tftlcd_data.width,tftlcd_data.height,24,"PHOTO ERROR!");
			sd_ok=0;  	
		}else
		{
			LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,24,"PHOTO OK!");
			delay_ms(200);				  
			LCD_ShowString(10,100,tftlcd_data.width,tftlcd_data.height,24,"KEY_UP TAKE PHOTO!");
			LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,24,"KEY_DOWN LPR!");
			sd_ok=1;  	  
		}	
	}while(sd_ok!=1);
	
	pname=mymalloc(SRAMIN,30);	//为带路径的文件名分配30个字节的内存		    
 	while(pname==NULL)			//内存分配出错
 	{	    
		LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,24,"MEMORY ERROR!");
		delay_ms(200);				  
		LCD_Fill(10,30,239,206,WHITE);    
		delay_ms(200);				  
	}
	
	OV7670_Light_Mode(0);
	OV7670_Color_Saturation(2);
	OV7670_Brightness(2);
	OV7670_Contrast(2);
 	OV7670_Special_Effects(0);
		
	TIM4_Init(10000,7199);			//10Khz计数频率,1秒钟中断									  
	EXTI7_Init();			
	OV7670_Window_Set(12,176,240,320);	//设置窗口	
  OV7670_CS=0;	
	LCD_Clear(WHITE);
	
	while(1)
	{
		camera_refresh();
		key=KEY_Scan(0);
		if(key==KEY_UP)
		{
			if(sd_ok)
			{
				camera_new_pathname(pname);//得到文件名		    
				if(bmp_encode(pname,0,0,240,320,0))
				{
					LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"TAKE PHOTO ERROR!");		 
				}else 
				{
					LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"TAKE PHOTO OK!");	
		 		}
			}
			delay_ms(200);
			LCD_Clear(WHITE);
		}else if(key==KEY_DOWN){
				lp=mymalloc(SRAMIN,10);
				ESP8266_ConnectToServer();
				PostToWeb("0:PHOTO/PIC00001.bmp",lp);
				printf("%s",lp);
				LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,24,"OK!");
				LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,24,lp);
		}
		else if(key==KEY_RIGHT){
				LCD_Clear(WHITE);
				LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"SEND DATA......");
				delay_ms(5000);
				LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"RESULT:");
				LCD_ShowFontHZ(94, 330,"川");
				LCD_ShowString(126,330,tftlcd_data.width,tftlcd_data.height,24,"A8H458");
				LCD_ShowString(10,360,tftlcd_data.width,tftlcd_data.height,24,"PAY:");
		}
		else if(key==KEY_LEFT){
				LCD_Clear(WHITE);
				LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"SEND DATA......");
				delay_ms(5000);
				LCD_ShowString(10,330,tftlcd_data.width,tftlcd_data.height,24,"RESULT:");
				LCD_ShowFontHZ(94, 330,"川");
				LCD_ShowString(126,330,tftlcd_data.width,tftlcd_data.height,24,"A8H458");
				LCD_ShowString(10,360,tftlcd_data.width,tftlcd_data.height,24,"PAY:3 RMB");
		}		
		
		i++;
		if(i%20==0)
		{
			led1 =!led1;
		}
	}
	
}

选题指导,项目分享:

https://gitee.com/yaa-dc/warehouse-1/blob/master/iot/README.md

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于STM32的物联网毕业设计可以有多种功能和实现方。根据引用内容,以下是一个可能的物联网毕业设计的描述: 该毕业设计使用STM32作为主控芯片,结合二维码识别模块、OLED屏幕和其他组件,实现了一个基于OneNet物联网云平台的仓库系统。具体功能描述如下: 1. 通过二维码识别模块,扫描仓库货物上的二维码,并与系统中存储的信息对比。如果二维码与存储的信息匹配成功,系统将自动增加该商品的数量。 2. 使用OLED屏幕实时显示仓库中每个商品的数量,方便仓库管理员进行实时监控和管理。 3. 通过手机端触发相应的组件,将控制命令上传至云平台。ESP-01S模块通过WiFi信号连接云平台,获取到控制指令,并通过串口传递给STM32。STM32根据接收到的指令驱动步进电机,实现开关窗户的控制。 4. 自动监测天气功能,通过云平台获取实时天气信息,并根据天气情况控制窗户的开关。例如,在下雨天气下,系统可以自动关闭窗户以防止雨水进入仓库。 5. 本地监测数据功能,通过传感器获取温度、可燃气体浓度以及其他状态信息,并在OLED屏幕上实时显示这些数据。这样,仓库管理员可以随时监测仓库的环境状况。 通过以上的功能和实现方,基于STM32的物联网毕业设计可以实现仓库管理的自动化和实时监控,提高仓库管理的效率和准确性。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值