深度学习入门(车牌识别)—— 手持式车辆违停管理系统

1.前言

题目来源东北大学的认知实习,为积累经验,主要的难度还是来源于1.OCR的训练,2.数据库的创建和连接,3.移植系统至移动端,主要流程如下:(当前只完成了主要功能,大佬勿喷QWQ)

 2.OCR以及数据集的选取

2.1PaddleOCR

关于深度学习的选取,查阅了很多资料,也看了很多文章,现在主流的det模型主要为yolov5为主,rec模型主要为CRNN或者LPRNet为主,以上的两种模型比较成熟,文件结构也有很多解读,大家也比较认可,官方网站如下:https://github.com/ultralytics/yolov5

但我选取OCR的时候,重点考虑到了算力的部分,我的笔记本为办公本,在使用yolov5进行训练中,一次只能训练数十张照片,训练效果极差,准确率也不行,所以选用办公本进行深度学习是很难的。

但PaddleOCR可以使用百度旗下的AI Studio进行训练(其实按理也可以训练其他的模型),由百度提供算力支持,可以大大节约时间和提高准确性,所以最后选择了百度的PaddleOCR

参考链接:智能交通-车牌识别 - 飞桨AI Studio (baidu.com)

2.2CCPD数据集

现有最大的车牌数据开源数据集:CCPD(Chinese City Parking Dataset, ECCV)

CCPD2019和CCPD2020,前者主要是蓝牌数据,约34W;后者主要是新能源绿牌数据,约1万

AI Studio提供上述两个数据集,并有额外的黄牌数据集:

 3.MySQL:数据库的创建与链接

3.1MySQL创建

MySQL官网:MySQL(具体安装教程网上很多,这里就不多赘述了)

MySQL的可视化管理工具,我使用的是:Navicat for MySQL,这是一个付费软件,不过网上也有很多学习版可以下载。

由于项目时间比较紧,而且我专业问题(为什么东B通信工程不学数据库???),所以只建立的一张表用于实现核心功能,主键为车牌,状态01表示是否违停:

如需在此基础上扩展功能,可以多添加几张表 

3.2后端与MySQL的链接与交互

主要功能为添加,删除,更改,列表,查找:

Python通过Pymysql以函数的形式实现:

(其中每个函数的输入和输出尽量规范性,用于判断是否成功)

1.添加

def insert_into(car):
    #查询重复添加

    i = find_mysql(car)

    print(i)

    if i != -1:
        i= -1
        return i

    # 建立数据库连接
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='chepaishibie',
        db='car_license'
    )

    # 创建游标对象
    cursor = conn.cursor()

    # 执行SQL插入语句
    sql = "INSERT INTO mysql (car_license, state) VALUES (%s, %s)"
    values = (car, 0)
    cursor.execute(sql, values)

    # 提交更改
    conn.commit()

    #判断是否插入成功
    if cursor.rowcount > 0:
        tik = 1
    else:
        tik = 0

    # 关闭游标和连接
    conn.close()
    cursor.close()

    return tik

2.删除

def delete_car(car):
    # 建立数据库连接
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='chepaishibie',
        db='car_license'
    )

    # 创建游标对象
    cursor = conn.cursor()

    # 执行删除语句
    sql = "DELETE FROM mysql WHERE car_license = %s"
    value = car
    cursor.execute(sql, (value,))

    # 提交更改
    conn.commit()

    # 关闭游标和连接
    cursor.close()
    conn.close()
    # 查询是否更改成功
    tik = find_mysql(car)

    if tik == -1:
        return 1
    else:
        return 0

3.更改

def update_car(car,new_state):
    # 建立数据库连接
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='chepaishibie',
        db='car_license'
    )

    # 创建游标对象
    cursor = conn.cursor()

    # 执行SQL更新语句
    sql = "UPDATE mysql SET state = %s WHERE car_license = %s"
    value1 = new_state
    value2 = car
    cursor.execute(sql, (value1, value2))

    # 提交更改
    conn.commit()

    # 关闭游标和连接
    cursor.close()
    conn.close()

4.列表

def list_mysql():
    # 建立数据库连接
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='chepaishibie',
        db='car_license'
    )

    # 创建游标对象
    cursor = conn.cursor()

    # 执行查询语句
    sql = "SELECT car_license, state FROM mysql"
    cursor.execute(sql)

    # 获取查询结果
    result = cursor.fetchall()

    # 将查询结果存放在一个二维数组中
    data_array = []
    for row in result:
        data_array.append(row)

     #关闭游标和连接
    cursor.close()
    conn.close()

    return data_array

5.查找

def find_mysql(car):
    # 建立数据库连接
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='chepaishibie',
        db='car_license'
    )

    # 创建游标对象
    cursor = conn.cursor()

    #查询是否存在
    sql = "SELECT car_license FROM mysql where car_license = %s"
    value = car
    cursor.execute(sql, (value,))

    result = cursor.fetchall()
    if result:
        tik=1
    else:
        tik=-1

    #根据是否存在进行下一步操作
    if tik==1:
        sql2 = "SELECT state FROM mysql where car_license = %s"
        value = car
        cursor.execute(sql2, (value,))
        result = cursor.fetchall()
        result_int = int(result[0][0])
        # 关闭游标和连接
        cursor.close()
        conn.close()
        return result_int
    else:
        # 关闭游标和连接
        cursor.close()
        conn.close()
        return tik

4.移动端部署

移动端部署也有很多方案,但很大的问题还是移动端算力问题,移动端是否能够轻松的运行整个程序是一件很难的事情,于是从工程上来讲,将需求算力的部分部署在服务器端是一件更优的方案

4.1HTML制作前端网页(JavaScript和CSS)

HTML教程可以参照:HTML 基础 | 菜鸟教程 (runoob.com)

小白感谢大佬的干货!

成品演示:(摄像头是主动关的)

 

以下是我的成品代码:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>车辆违停拍照</title>
<meta content="" name="Keywords" />
<meta content="" name="Description"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<meta name="format-detection" content="telephone=no, email=no">
<meta name="HandheldFriendly" content="true" />
</head>
<body>


<style type="text/css">
*{  padding:0; margin:0; }
body{ padding:0 10px }
h1,h2,h3{ margin:10px 0; }
#video{ background:#000; display:block; }
#snap{ width:100px; height:40px; line-height:40px; margin:10px 0;     }
</style>

<h1>手持式车辆违停系统网页端</h1>
<h2 id="right"></h2>
<h3 id="support"></h3>
<video id="video" width="320" height="320"></video>
<button id="snap" >拍照</button>
<canvas id="canvas" style="display:none" width="320" height="320"></canvas>
<script>

	//判断浏览器是否支持HTML5 Canvas
	window.onload = function () {
	try {
		//动态创建一个canvas元 ,并获取他2Dcontext。如果出现异常则表示不支持 document.createElement("canvas").getContext("2d");
		document.getElementById("support").innerHTML = "浏览器支持拍照";
		takePhotos();
	}
	catch (e) {
		document.getElementById("support").innerHTML = "浏览器不支持拍照";}
	};


	//拍照主函数
	function takePhotos(){
			//这段代 主要是获取摄像头的视频流并显示在Video 签中
			var canvas = document.getElementById("canvas"),
			context = canvas.getContext("2d"),
			video = document.getElementById("video");

			function successCallback(stream) {
				// Set the source of the video element with the stream from the camera
				if (video.mozSrcObject !== undefined) {
					video.mozSrcObject = stream;
				} else {
					video.srcObject = stream;
				}
				video.play();
			}

			function errorCallback(error) {
				 alert('错误代码: [CODE ' + error.code + ']');
				// Display a friendly "sorry" message to the user
			}

			navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
			window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

			// Call the getUserMedia method with our callback functions
			if (navigator.getUserMedia) {
				navigator.getUserMedia({video: true}, successCallback, errorCallback);
			} else {
				alert('浏览器不支持getUserMedia.');
				// Display a friendly "sorry" message to the user
			}


			//这个是拍照按钮的事件,
			document.getElementById("snap").onclick = function(){
			context.drawImage(video, 0, 0, 320, 320);
			//获取浏览器页面的画布对象
			var canvas = document.getElementById("canvas");
			//以下开始编 数据
			var imageData = canvas.toDataURL();
			//将图像转换为base64数据
			var img = new Image();
			img.src = imageData;
			var xhr = new XMLHttpRequest();
			xhr.onload = function() {
			if (xhr.status >= 200 && xhr.status < 300) {
			// 处理响应数据
			var response = xhr.responseText;
			document.getElementById("right").innerHTML = response;
			} else {
			// 处理错误
			document.getElementById("right").innerHTML = 'error';  }
			};
			xhr.open('post','/upload');
			var formData = new FormData();
			formData.append('image', img.src);
			xhr.send(formData);
		  }
	}
 </script>


</body>
</html>

4.2Flask后端程序

关于flask这个python的web框架,网上也有很多教程可以学习,此项目的主要功能,主要为网页端上传照片,服务端识别并标记该车牌号,并返回结果。

我的源代码为:

from flask import Flask, request, jsonify, render_template
from flask import Flask, request, make_response
from text_output import car_det_rec
from car_mysql_storage import find_mysql,update_car
import base64

app = Flask(__name__)
app.config['DEFAULT_ENCODING'] = 'UTF-8'

@app.route('/')
def index():
    return render_template('test.html')


@app.route('/upload', methods=['POST'])
def upload():
    formData = request.form
    image_data = formData.get('image')
    image_binary = image_data.split(',')[1]
    with open('image.png', 'wb') as f:
        f.write(base64.b64decode(image_binary))
    image_path='D:/python-yolo5/paddleocr-develop/car-manage/image.png'
    car=car_det_rec(image_path)
    check_car=find_mysql(car)
    if check_car==-1:
        tik='不存在'
    else:
        update_car(car,'1')
        tik='已标记违停'
    car.insert(1, tik)
    content = b'\n'.join([s.encode('utf-8') for s in car])
    response = make_response(content)
    response.charset = 'utf-8'
    return response


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80, debug=True)

5.总结

本项目基本完成了手持式车辆违停管理系统的基本功能,还有一个后端的数据库管理系统,使用tkinter制作的ui,也学习到很多没有学过的东西,但还有很多地方可以优化的地方

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标识别是计算机视觉一个重要的研究领域,由此延伸出的车辆型号识别具有重 要的实际应用价值,特别是在当今交通状况复杂的大城市,智能交通系统成为发展趋 势,这离不开对车辆型号进行识别和分类的工作,本文围绕如何利用计算机视觉的方 法进行车辆型号的识别和分类展开了一系列研究: 本文对当前的目标识别和分类的特征和算法做了总结和归纳。分析比较了作为图 像特征描述常见的特征算子,总结归纳了他们的提取方法、特征性能以及相互之间的 关联。另外,介绍了在目标识别工作中常用的分类方法,阐述了他们各自的原理和工作 方法。研究了深度神经网络的理论依据,分析比较了深度神经网络不同的特征学习方 法,以及卷积神经网络的训练方法。分析比较不同特征学习方法的特点选取 k-means 作为本文使用的特征学习方法,利用卷积神经网络结构搭建深度学习模型,进行车辆 车型识别工作。 本文为了测试基于深度学习的车辆型号分类算法的性能在 30 个不同型号共 7158 张图片上进行实验;并在相同数据上利用改进了的 SIFT 特征匹配的算法进行对比实验; 进过实验测试,深度学习方法在进行车型分类的实验中取得 94%的正确率,并在与 SIFT 匹配实验结果对比后进一步证实:深度学习的方法能够应用在车辆型号识别领域

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值