"vscode:/vscode.git/clone" did not exist on "a02a5490baab3b4745844b0f0752fe746a0cb7bc"
Commit bc2ea059 authored by liuhy's avatar liuhy
Browse files

Merge branch 'dev' into 'master'

Dev

See merge request modelzoo/lpr!1
parents b44aeb9e b1430a7d
File added
import onnxruntime as ort
import cv2
import numpy as np
import argparse
import os
import time
print('Runing Based On:', ort.get_device())
......@@ -40,24 +43,39 @@ def LPRNetPostprocess(infer_res):
result = ''.join(list(map(lambda x: CHARS[x], no_repeat_blank_label)))
return result
def LPRNetInference(model, imgs):
img = LPRNetPreprocess(imgs)
def LPRNetInference(args):
if ort.get_device() == "GPU-MIGRAPHX":
sess = ort.InferenceSession(args.model, providers=['ROCMExecutionProvider'],) #DCU版本
else:
sess = ort.InferenceSession(args.model, providers=['CPUExecutionProvider']) # CPU版本
if ort.get_device() == "GPU":
# sess = ort.InferenceSession(model, providers=['CUDAExecutionProvider'],) #GPU版本
sess = ort.InferenceSession(model, providers=['ROCMExecutionProvider'],) #DCU版本
if os.path.isdir(args.imgpath):
images = os.listdir(args.imgpath)
count = 0
time1 = time.perf_counter()
for image in images:
img = LPRNetPreprocess(os.path.join(args.imgpath, image))
intput = sess.get_inputs()[0].shape
preb = sess.run(None, input_feed={sess.get_inputs()[0].name: img})[0]
result = LPRNetPostprocess(preb)
if result == image[:-4]:
count += 1
print('Inference Result:', result)
time2 = time.perf_counter()
print('accuracy rate:', count / len(images))
print('average time', (time2 - time1)/count*1000)
else:
sess = ort.InferenceSession(model, providers=['CPUExecutionProvider']) # CPU版本
print(sess.get_providers())
img = LPRNetPreprocess(args.imgpath)
intput = sess.get_inputs()[0].shape
preb = sess.run(None, input_feed={sess.get_inputs()[0].name: img})[0]
result = LPRNetPostprocess(preb)
return result
print('Inference Result:', result)
if __name__ == '__main__':
model_name = 'model/LPRNet.onnx'
# model_name = 'LPRNet.onnx'
image = 'imgs/川JK0707.jpg'
InferRes = LPRNetInference(model_name, image)
print(image, 'Inference Result:', InferRes)
parser = argparse.ArgumentParser(description='parameters to vaildate net')
parser.add_argument('--model', default='model/LPRNet.onnx', help='model path to vaildate')
parser.add_argument('--imgpath', default='imgs', help='the image path')
args = parser.parse_args()
LPRNetInference(args)
......@@ -5,6 +5,9 @@ MIGraphX示例程序
import cv2
import numpy as np
import migraphx
import argparse
import os
import time
CHARS = ['京', '沪', '津', '渝', '冀', '晋', '蒙', '辽', '吉', '黑',
'苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤',
......@@ -42,30 +45,47 @@ def LPRNetPostprocess(infer_res):
result = ''.join(list(map(lambda x: CHARS[x], no_repeat_blank_label)))
return result
def LPRNetInference(model_name, imgs):
img = LPRNetPreprocess(imgs)
def LPRNetInference(args):
# 加载模型
if model_name[-3:] == 'mxr':
model = migraphx.load(model_name)
if args.model[-3:] == 'mxr':
model = migraphx.load(args.model)
else:
model = migraphx.parse_onnx(model_name)
# migraphx.quantize_fp16(model)
print('convert onnx to mxr...')
model = migraphx.parse_onnx(args.model)
model.compile(t=migraphx.get_target("gpu"),device_id=0) # device_id: 设置GPU设备,默认为0号设备(>=1.2版本中支持)
# migraphx.save(model, 'LPRNet.mxr')
migraphx.save(model, args.savepath)
if os.path.isdir(args.imgpath):
images = os.listdir(args.imgpath)
count = 0
time1 = time.perf_counter()
for image in images:
img = LPRNetPreprocess(os.path.join(args.imgpath, image))
inputName = model.get_parameter_names()[0]
inputShape = model.get_parameter_shapes()[inputName].lens()
# print("inputName:{0} \ninputShape:{1}".format(inputName,inputShape))
results = model.run({inputName: migraphx.argument(img)})
result = LPRNetPostprocess(np.array(results[0]))
if result == image[:-4]:
count += 1
print('Inference Result:', result)
time2 = time.perf_counter()
print('accuracy rate:', count / len(images))
print('average time', (time2 - time1)/count*1000)
else:
img = LPRNetPreprocess(args.imgpath)
inputName=model.get_parameter_names()[0]
inputShape=model.get_parameter_shapes()[inputName].lens()
print("inputName:{0} \ninputShape:{1}".format(inputName,inputShape))
# print("inputName:{0} \ninputShape:{1}".format(inputName,inputShape))
results = model.run({inputName: migraphx.argument(img)})
result = LPRNetPostprocess(np.array(results[0]))
return result
print('Inference Result:', result)
if __name__ == '__main__':
# model_name = 'LPRNet.onnx'
model_name = 'model/LPRNet.mxr'
image = 'imgs/川JK0707.jpg'
InferRes = LPRNetInference(model_name, image)
print(image, 'Inference Result:', InferRes)
parser = argparse.ArgumentParser(description='parameters to vaildate net')
parser.add_argument('--model', default='model/LPRNet.onnx', help='model path to inference')
parser.add_argument('--imgpath', default='imgs', help='the image path')
parser.add_argument('--savepath', default='model/LPRNet.mxr', help='mxr model save path and name')
args = parser.parse_args()
LPRNetInference(args)
# license-plate-detect-recoginition-pytorch
深度学习车牌检测与识别,检测结果包含车牌矩形框和4个角点,基于pytorch框架运行,
主程序是detect_rec_img.py,运行程序前需要确保您的机器安装了pytorch
<!--
* @Author: liuhy
* @email: liuhy6@sugon.com
* @Date: 2023-03-03 10:17:07
* @LastEditTime: 2023-03-03 15:38:01
* @FilePath: \lpr\README.md
-->
# License-Plate-Recoginition(LPR)
## 模型介绍
LPR是一个基于深度学习技术的车牌识别模型,主要识别目标是自然场景的车牌图像。
## 模型结构
模型采用LPRNet,模型结构主要包含三部分:一个轻量级CNN主干网络、基于预定位置的字符分类头部、基于贪婪算法的序列解码。此外模型使用CTC Loss和RMSprop优化器。参考论文[LPRNet: License Plate Recognition via Deep Neural Networks](https://arxiv.org/pdf/1806.10447v1.pdf)
## 数据集
推荐使用一个车牌数据集[CCPD](https://github.com/detectRecog/CCPD "CCPD官网GitHub"),该数据集由中科大收集,可用于车牌的检测与识别。
车牌识别模块,可以更换成crnn网络做识别,也可以更换到传统图像处理方法分割字符后逐个字符识别,
在这个车牌检测和识别系统里,我觉得最重要的是前面的车牌检测与矫正模块,因为如果前面没做好,
那么后面输入到车牌识别模块里的图片是一个倾斜的车牌,这时候输出结果就出错了。
我们提供了一个脚本cut_ccpd.py用于剪裁出CCPD数据集中的车牌位置,以便用于LPR模型的训练,在cut_ccpd.py中修改img_path和save_path即可,分别是CCPD数据集中ccpd_base文件夹的路径和剪裁出的图像保存路径。LPR用于训练的数据文件名就是图像的标签。**数据集使用固定的大小94x24。** 使用方法:
对于车牌检测,也可以使用图像分割的思想,例如使用UNet语义分割网络,分割出车牌,
二值化然后查找连通域,计算4个顶点
python cut_ccpd.py \
--ccpdpath CCPD数据集下ccpd_base文件夹路径 \
--savepath 保存切割图像的路径
## 训练及推理
### 环境配置
[光源](https://www.sourcefind.cn/#/service-details)可拉取训练以及推理的docker镜像,在[光合开发者社区](https://cancon.hpccube.com:65024/4/main/)可下载Migraphx和ONNXruntime安装包。LPR推荐的镜像如下:
* 训练镜像:docker pull image.sourcefind.cn:5000/dcu/admin/base/vscode-pytorch:1.10.0-centos7.6-dtk-22.10-py37-patch4
* 推理镜像:docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:migraphx2.5.0_centos7.6-dtk-22.10.1
### 训练与Fine-tunning
LPR模型的训练程序是train.py,初次训练模型使用以下命令:
python train.py \
--train_img_dirs 训练集文件夹路径 \
--test_img_dirs 验证集文件夹路径
Fine-tunning使用以下命令:
python train.py \
--train_img_dirs 训练集文件夹路径 \
--test_img_dirs 验证集文件夹路径 \
--pretrained_model 预训练模型路径 \
--resume_epoch Fine-tuning训练的起始epoch \
--max_epoch 训练的最大epoch
Fine-tuning时只训练从起始epoch到最大epoch。
### 预训练模型
在model文件夹下我们提供了一个预训练模型以及对应的onnx模型和mxr模型,以下是相关子目录的介绍:
LPR
├── imgs #测试图像
├── model
│   ├── lprnet.pth #基于pytorch框架训练出的LPR预训练模型
│   ├── LPRNet.onnx #由lprnet.pth转换的onnx模型
└── └── LPRNet.mxr #用migraphx编译LPRNet.onnx得到的离线推理模型
### 测试
LPR模型用test.py对训练出的模型进行测试,使用方法如下:
python test.py \
--model 需要测试的pth模型路径 \
--imgpath 测试集路径(文件夹或图像皆可) \
--export_onnx True/False(该参数用于选择是否需要将pth模型转为onnx模型) \
--dynamic True/False(该参数用于选择onnx模型是否使用动态的batch size)
### 推理
我们分别提供了基于ONNXruntime(ORT)和Migraphx的推理脚本,版本依赖:
* ONNXRuntime(DCU版本) >= 1.14.0
* Migraphx(DCU版本) >= 2.5.0
#### ORT
LPRNet_ORT_infer.py是基于ORT的的推理脚本,使用方法:
python LPRNet_ORT_infer.py \
--model onnx模型路径 \
--imgpath 数据路径(文件夹或图像皆可)
#### Migraphx
LPRNet_migraphx_infer.py是基于Migraphx的推理脚本,使用需安装好Migraphx,支持onnx模型和mxr模型推理,mxr模型是migraphx将onnx模型保存成的离线推理引擎,初次使用onnx模型会保存对应的mxr模型。使用方法:
python LPRNet_migraphx_infer.py \
--model mxr/onnx模型路径 \
--imgpath 数据路径(文件夹或图像皆可) \
--savepath mxr模型的保存路径以及模型名称
## 性能和准确率数据
测试数据使用的是[LPRNet_Pytorch](https://github.com/sirius-ai/LPRNet_Pytorch/tree/master/data/test),使用的加速卡是DCU Z100。**mxr格式的模型是migraphx创建的onnx模型的离线引擎。**
| Engine | Model Path| Model Format | Accuracy(%) | Speed(ms) |
| :------: | :------: | :------: | :------: |:------: |
| ONNXRuntime | model/LPRNet.onnx | onnx | 91.0 | 2.59 |
| Migraphx | model/LPRNet.onnx |onnx | 91.0 | 2.66 |
| Migraphx | model/LPRNet.mxr |mxr | 91.0 | 2.49 |
## 参考
* [LPRNet_Pytorch](https://github.com/sirius-ai/LPRNet_Pytorch)
* [license-plate-detect-recoginition](https://github.com/qzpzd/license-plate-detect-recoginition)
'''
Author: liuhy
email: liuhy6@sugon.com
Date: 2023-03-03 10:17:07
LastEditTime: 2023-03-03 11:28:33
FilePath: \lpr\cut_ccpd.py
'''
# -*- coding: utf-8 -*-
# @Author: liuhy
# @Email: 17603873430@163.com
# @Date: 2023-02-28 15:14:13
# @Last Modified time: 2023-03-01 17:52:20
# coding:utf-8
import os
import cv2
import time
import argparse
provinces = ['皖', '沪', '津', '渝', '冀', '晋', '蒙', '辽', '吉', '黑', '苏', '浙', '京', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤', '桂', '琼', '川', '贵', '云', '藏', '陕', '甘', '青', '宁', '新', '警', '学', 'O']
alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', 'O']
ads = ['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', 'O']
def cut_img(img_path, save_path):
images = os.listdir(img_path)
for i, image in enumerate(images):
try:
print('\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bProcessing:%s'%i, end='',flush=True)
img = cv2.imread(os.path.join('ccpd_base', image))
info = image.split('-')
r1, r2, l1, l2 = info[3].split('_')
rx1, ry1 = r1.split('&')
lx1, ly1 = l1.split('&')
im = img[int(ly1):int(ry1), int(lx1):int(rx1)]
label_index = info[4].split('_')
label = provinces[int(label_index[0])]
label += alphabets[int(label_index[1])]
if label_index[2].isalnum():
label += ads[int(label_index[2])]
else:
label += alphabets[int(label_index[2])]
label += ads[int(label_index[3])]
label += ads[int(label_index[4])]
label += ads[int(label_index[5])]
label += ads[int(label_index[6])]
im = cv2.resize(im, (94, 24))
if os.path.exists(save_path) is False:
os.mkdir(save_path)
cv2.imencode('.jpg', im)[1].tofile(save_path + '/' + label + '.jpg')
except Exception as e:
print('wrong image:', image)
if __name__=='__main__':
parser = argparse.ArgumentParser(description='parameters to vaildate net')
parser.add_argument('--ccpdpath', default='CCPD/ccpd_base', help='model path to vaildate')
parser.add_argument('--savepath', default='CCPD/lpr', help='the image path')
args = parser.parse_args()
cut_img(args.ccpdpath, args.savepath)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment