车牌检测识别

该项目介绍了基于yolov5进行车牌检测和LPRNet进行车牌识别的流程,包括数据集的准备、模型训练、转换和部署到AidLux手机端的过程。文章强调了针对不同应用场景选择合适算法的重要性,并提供了数据集整理和模型转换的详细步骤。
摘要由CSDN通过智能技术生成

---------------
7月更新训练项目:
新的车牌检测+关键点检测+车牌矫正:
https://aistudio.baidu.com/aistudio/projectdetail/6545272
LPRNet矫正后的车牌识别:
https://aistudio.baidu.com/aistudio/projectdetail/5628649
---------------
3月14日更新内容:
网络训练:添加了yolov5和LPRNet的训练过程
https://aistudio.baidu.com/aistudio/projectdetail/5557065
https://aistudio.baidu.com/aistudio/projectdetail/5628649
模型转换:总结了onnx转tflite的更多细节
https://blog.csdn.net/kalahali/article/details/129538442
部署:新增aistudio项目模型部署差异
----------------

AidLux智慧社区AI实战总结之车牌检测与识别,基于yolov5实现车牌检测,加上LPRNet对检测到的车牌进行识别来实现整个识别流程,最后通过AidLux实现在手机端的部署

项目资料/代码:

https://pan.baidu.com/s/147gi2MLqC6KiBGHyzSsbkw 提取码:aid3
手机端需要下载aidlux软件

算法方案

算法方案需要考虑应用场景,不同场景,车牌识别的算法方案也不一样,比如:

  1. 在加油站的车牌识别场景中,车占整个图片的比例较小时,则建议在车牌检测前,增加一个车的检测模块。在检测到车后,再对车进行车牌的检测和识别。(避免漏检)

image.png

  1. 在智慧社区或停车场的场景中,相机一般安装在正对车牌的位置,车牌占据图片的比例比较大,这样建议直接对车牌做检测和识别

5cf1c8b6e49310483587134325ea639.jpg
本项目正是基于智慧社区的应用场景,所以选择算法方案为车牌检测yolov5和车牌识别LPRNet
注意,在实际应用场景中,如果车牌在图片中的倾角较大,一般车牌的水平度和垂直度超过15°,则需要考虑加入矫正,算法方案应为:车牌检测+车牌矫正+车牌识别
这里的智慧社区的车与相机位置可以相对平行固定,故不添加矫正
image.png

数据准备

数据集简介

考虑到智慧社区中,在社区内很少出现工程车辆,所以只需要覆盖大部分的蓝牌和绿牌的场景即可。最普遍的开源车牌数据集是中科大的CCPD数据集,官网链接是:https://github.com/detectRecog/CCPD
中科大车牌数据集有CCPD2019和CCPD2020,其中CCPD2019主要为蓝牌,CCPD2020为绿牌。其中蓝牌是燃油车,绿牌是电动车。
这里我们主要用CCPD2019的蓝牌来作为我们的任务,官网有百度网盘链接:
image.png

Images in CCPD-Base is split to train/val set. Sub-datasets (CCPD-DB, CCPD-Blur, CCPD-FN, CCPD-Rotate, CCPD-Tilt, CCPD-Challenge) in CCPD are exploited for test.

用于训练的数据在CCPD-Base中,从这里划分训练集和验证集
用于测试的数据则有:
CCPD-DB:车牌区域交亮,较暗或则不均匀
CCPD-Blur:由于相机抖动而导致的模糊车牌
CCPD-FN: 车牌距离摄像头较近或则较远
CCPD-Rotate: 旋转/倾角
CCPD-Challenge: 有挑战性
CCPD-Tilt:

数据集格式

每张图片的标签为文件名:
图片命名:“0019-1_1-340&500_404&526-404&524_340&526_340&502_404&500-0_0_11_26_25_28_17-66-3.jpg”
image.png

# 详细解释:
"""
0019:
	车牌区域占整个画面的比例;
1_1: 		
	车牌水平和垂直角度, 水平1°, 竖直1°
340&500_404&526:	
	标注框左上、右下坐标,左上(154, 383), 右下(386, 473)
404&524_340&526_340&502_404&500:	
	标注框四个角点坐标,顺序为右下、左下、左上、右上
0_0_11_26_25_2_8:
	车牌号码, 映射关系如下: 
 		第一个0为省份 对应省份字典provinces中的’皖’,;
        第二个0是该车所在地的地市一级代码,对应地市一级代码字典alphabets的’A’;
        后5位为字母和文字, 查看车牌号ads字典,如11为M,26为2,25为1,2为C,8为J 最终车牌号码为皖AM21CJ
映射列表:
    省份:[“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”]
    地市:[‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’,‘X’, ‘Y’, ‘Z’]
    车牌字典:[‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,‘Y’, ‘Z’, ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’]
"""

需要先对图片的标签解析,解析完后才能对其进行训练。
因为中科大在安徽采集数据较多,其中“皖”字占整个数据集汉字的90%,所以如果是对智慧社区定制化开发,需考虑社区所在的地理位置,针对性采集数据,或者模拟数据,优化模型。

数据集整理

因要做两个任务,车牌检测、车牌识别。所以将车牌数据集整理分成两个部分:一是整理成检测任务需要的数据集,二是整理成车牌识别任务需要的数据集。
由于数据量较大,为防止出错,这里分为两步:

  1. 简单验证:

    先将几张图片标签转成yolo文件,并通过yolo转成voc xml格式,用labelimg打开校验。

  2. 批量转换:

    确认转换的方式没有问题后,将所有标签直接转换成yolo格式保存。
    转yolo格式以及yolo转voc格式的脚本在代码资源中位置:tools/ParaseData.py
    转换voc之后用labelimg打开图片文件夹,并查看xml_labels结果,标注的label转换没有问题:
    image.png
    检查没问题后将脚本中的validation设置成False,修改图片路径和保存txt路径:image.png
    考虑训练时长等因素,可以使用脚本tools/cp10000.py,将数据随机抽取1万张来训练,若后期效果不好,可以用8w多张数据重新训练。

车牌识别数据集处理

对于车牌识别步骤,需要将车牌裁切出来作为训练数据,脚本为ools/ccpd2lpr.py,生成以车牌号为文件名的数据集。
image.png

网络训练

训练部分就是yolov5和lprnet的训练。
本人没有GPU电脑,这里选择的是云服务器,除了AutoDL平台,这次白嫖百度飞浆AIStudio平台的算力来训练,项目地址如下,可以直接fork后开启训练:

yolov5

直接使用PaddleYOLO项目快速开启训练
https://aistudio.baidu.com/aistudio/projectdetail/5557065

LPRNet

以下是转写paddle后的训练项目:
https://aistudio.baidu.com/aistudio/projectdetail/5628649

在云服务器上训练并生成onnx文件后,将onnx下载到本地准备下一步部署
若使用torch,可以参考项目资料里的参考代码train_yolov5.py和train_lprnet.py
训练完后保存好pt模型。

测试

yolov5测试代码参考detect_yolov5.py(输出结果在demo/detect_results)
image.png
测试车牌识别的脚本test_lprnet.py
需要注意的是车牌识别作为车牌检测的下游任务,其输入图片需要将检测到的裁剪车牌
image.png
整个流程串联起来的测试脚本detect_torch_pipeline.py
image.png

Android端部署

AidLux

AidLux是安装在ARM架构下的,跨生态(Android/鸿蒙+Linux)一站式开发和部署平台APP。必须要在安卓手机或者安卓的平板上或ARM板卡才能下载运行,设备需要满足ARM64位,安卓6.0以上。可以在手机应用商城搜索下载。
当然如果后面在手机上操作编程有点麻烦,可以通过IP的方式,在局域网内直接映射到电脑上操作。可以点击页面最上方的Cloud_ip,浏览器在手机访问。
image.pngimage.png
浏览器进入桌面的默认密码是:aidlux
可以浏览器桌面方便的传输文件。
image.png
这里贴上aidlux图像处理相关的文档地址:https://docs.aidlux.com/#/api/?id=%e5%9b%be%e5%83%8f%e5%a4%84%e7%90%86

vscode远程连接

使用vscode的remote功能,可以远程连接手机,方便编写代码,ssh配置如下:
hostname需要为cloud_ip里的地址,连接的密码都是aidlux
image.png

模型转换

pt模型移植到Android还需要转换成Android端适配的模型,一般适配的轻量化模型如ncnn, tflite, paddlelite等,这里选择这里我们选择的tflite模型,不过pytorch直接转tflite的工具不齐全,一般都会转成序列化成onnx,再轻量化模型, 以pytorch->onnx->tflite 方式。

转换onnx

yolov5代码中自带导出代码,配置export_yolov5.py中的配置代码,修改weights路径导出onnx
可以在netron查看网络结构https://netron.app/
lprnet的导出代码在export_lprnet.py
注意lprnet网络中的maxpool3d没有被官方支持,这里将maxpool3d用两个maxpool2d去实现(代码里已经修改了)
基于onnx的前向推理可参考detect_onnx_inference.py
image.png

onnx转tflile

模型转换的注意事项还可参考总结:
https://blog.csdn.net/kalahali/article/details/129538442

参考代码export_tflite.py

from onnx_tf.backend import prepare
import onnx
 
TF_PATH = "weights/LPRNet_Simplified.pb" # where the representation of tensorflow model will be stored
ONNX_PATH = "weights/LPRNet_Simplified.onnx" # path to my existing ONNX model
onnx_model = onnx.load(ONNX_PATH)  # load onnx model
tf_rep = prepare(onnx_model)  # creating TensorflowRep object
tf_rep.export_graph(TF_PATH)
 
import tensorflow as tf
 
TF_PATH = "weights/LPRNet_Simplified.pb"
TFLITE_PATH = "weights/LPRNet_Simplified.tflite"
converter = tf.lite.TFLiteConverter.from_saved_model(TF_PATH)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tf_lite_model = converter.convert()
with open(TFLITE_PATH, 'wb') as f:
    f.write(tf_lite_model)

pc端的tflite推理参考detect_tflite_pipeline.py
需要注意,在netron中看到yolov5.tflite模型的输出output顺序是40,20,80,在tflite模型输出后处理的时候需要注意anchor的对应。
image.png
image.png

部署

参考代码detect_aidlux_inference.py
需要注意模型的in_shape 和out_shape 要与netron中查看的输入输出保持一致,并且还要*4,表示float32有4个字节
跟多关于aidlite.ANNModel的详细信息可以在前面提到文档中查看:https://docs.aidlux.com/#/api/?id=annmodel
修改自己的两个模型路径后,运行
image.png
另外关于cv2不支持中文可以参考下面测试案例,利用PIL实现和cv2.putText的相同效果:

import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2


def cv2AddChinese(img, text, position, fontScale=1., textColor=(0,255,0)):
    if (isinstance(img, np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    baseFontSize = 34  # 以此字体大小进行缩放,字体高度
    height = baseFontSize*0.8  # 字体实际高度,去空白
    x, y = position
    position_new = (x, y-fontScale*height)
    fontsize = int(fontScale * baseFontSize)
    draw = ImageDraw.Draw(img)
    # SimHei.ttf为字体文件,可在网上下载,若读取失败,改为完整路径
    fontStyle = ImageFont.truetype("SimHei.ttf", fontsize, encoding="utf-8")  
    # width, height = fontStyle.getsize(text)  # 获取字体宽高
    draw.text(position_new, text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

text = "Chines中文"
img_dir = 'test.JPG'  # 自己的测试图片
position = (0, 40)
fontScale = 1.5
img_data = cv2.imread(img_dir)
img_data = cv2AddChinese(img_data, text, position, fontScale, (0,255,0))

# t_size = cv2.getTextSize(text, 0, fontScale, thickness=2)  # cv2获取字体宽高
cv2.putText(img_data, text, position, 0, fontScale, (255,0,0), 2)
cv2.imshow('demo', img_data)
cv2.waitKey(1000)
aistudio项目模型部署差异

这里新增一小节,对上文中提到的aistudio训练项目模型与本文资料包代码的区别做个说明

  1. yolov5的训练模型与资料包不同,aistudio训练的yolov5_n,输出shape为(1,25200,5),是检测框未缩放未缩放回原图尺寸的检测框坐标+分类置信度。所以在aidlux中需要注意:
# 模型的导入
det_model_path = '模型的存放位置'
in_shape0 = [1 * 3* 640 * 640 * 4]  # 4是4个字节,float32
out_shape0 = [1 * 25200 * 5 * 4]
aidlite.ANNModel(det_model_path, in_shape0, out_shape0, 4, -1)
  1. 相应的,检测模型的后处理也需要修改:
def det_poseprocess(outputs, imgsz, scale, left, top ,conf_thresh, iou_thresh):
    # nms
    true_conf = outputs[..., 4]
    mask = true_conf > conf_thresh
    # 调整为原图下的坐标
    pred = outputs[mask][:, :4]
    boxes = np.zeros_like(pred)
    boxes[:, 0] = pred[:, 0] - left
    boxes[:, 2] = pred[:, 2] - left
    boxes[:, 1] = pred[:, 1] - top
    boxes[:, 3] = pred[:, 3] - top
    boxes /= scale
    confs = true_conf[mask]
    keep = non_max_suppression(boxes, confs, iou_thresh=0.5)
    boxes = boxes[keep]
    confs = confs[keep].reshape((-1, 1))
    classes = np.zeros_like(confs).reshape((-1, 1))
    return boxes, confs, classes
  1. 对于LPRNet的车牌识别模型,训练的时候使用的图片是RGB格式,所以如果是cv2读取的图片数据需要在图片前处理中将图片从BGR转为RGB
# reg_preprocess
img_crop = cv2.cvtColor(img_crop, cv2.COLOR_BGR2RGB)

手机端运行效果:

使用aidlux在手机端部署车牌检测识别


对于车牌识别的流程,数据中“皖”字开头的牌照占整个数据集汉字的90%,想要更好的效果,还需针对性采集数据,或者模拟数据,来优化模型。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: labelimg是一款用于图像标注的工具,可以实现对车牌的标注。在使用labelimg标注车牌时,需要先将车牌图像导入该工具,然后选取“框选工具”或“多边形工具”对车牌进行标注。在选取工具后,就可以在车牌图像上进行标注,将车牌的位置和轮廓用矩形或多边形框住。标注完成后,将标注好的车牌信息导出保存为xml或txt格式,即可应用于车牌识别中。 车牌识别是一种基于计算机视觉的技术,通过图像处理和模式识别等方法,实现对车牌字符的识别和提取。标注车牌车牌识别的前置工作,是实现自动识别的必要条件。因为车牌的形状、颜色和字体等特征都具有复杂性和多样性,所以需要采用有效的标注工具和标注方法,保证标注的准确性和效率。labelimg是一款很好用的图像标注工具,能够有效满足车牌标注的需求,是车牌识别技术的重要工具之一。 ### 回答2: labelimg是一款非常优秀的图像标注工具,可以用于标注车牌等各种物体。在标注车牌时,一般需要按照以下步骤进行: 首先,在labelimg中载入待标注的图片。可以通过在工具栏中打开“Open Dir”来选择需要标注的文件夹,或者直接拖拽图片文件到工作区域来加载。 然后,使用鼠标框选出车牌区域,并在工具栏中选择“Create RectBox”来创建一个矩形框,将这个矩形框调整到车牌区域并进行细微调整。 接着,对车牌区域进行标注。在工具栏中选择“Create Main Label”来创建一个主要的标注,例如“车牌”、“LP”等,然后在相应的矩形框内输入车牌的具体信息。 最后,保存标注结果。可以在工具栏中选择“Save”来保存标注结果,或者选择“Next Image”来标注下一张图片。 通过以上步骤,就可以用labelimg快速、准确地标注车牌,为后续的图像处理、识别等工作提供便利。同时,labelimg本身还具备多种高级功能,例如多标签支持、图像增强、导出标注结果等,能够满足各种场景下的需求。 ### 回答3: labelimg是一个图像标注工具,可以用户在图片中标注物件。对于车牌这种需要精确标注的物件,在图像识别领域也是一个广泛应用的场景。使用labelimg可以通过在图片中框出车牌区域并进行标注,来训练出一个能够识别车牌的模型。车牌的标注包括车牌的位置、大小、颜色、文字等信息。标注的精度和质量对于训练模型的效果至关重要。 使用labelimg标注车牌时,需要对车牌进行初步的分析和提取。这一过程可以采用数字图像处理技术,通过提取图像颜色、形状和纹理等特征来识别出可能的车牌区域。然后借助labelimg工具可以将车牌框出并标注。标注车牌时,需要考虑车牌旋转、遮挡等情况,以提升模型对不同场景的适应性。 标注完车牌后,可以使用深度学习算法进行训练,通过大量的车牌数据和标注集,训练出精准识别车牌的模型。识别车牌在实际应用中可以用于车辆安全管理、交通违章监测、物流配送等方面,有着广泛的应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值