闲来无事,想复现一下网上的基于YOLO v5的单目测距算法。然后就突然想在这个场景下搞一下车牌识别,于是就有了这篇文章。今天就给大家分享基于HyperLPR3实现车牌检测和识别。
原创作者:RS迷途小书童
博客地址:https://blog.csdn.net/m0_56729804?type=blog
1、HyperLPR3介绍
HyperLPR3是一个高性能开源中文车牌识别框架,由北京智云视图科技有限公司开发。它是一个基于Python的深度学习实现,用于中文车牌的识别。与开源的EasyPR相比,HyperLPR3在检测速度、鲁棒性和多场景的适应性方面都有更好的表现。
HyperLPR3支持多种类型的车牌,包括新能源汽车等。其安装和使用都非常方便,可以通过Python的pip工具直接进行安装,并使用命令行工具对本地图像或在线URL进行快速测试。
此外,HyperLPR3还支持PHP、C/C++、Python语言,以及Windows/Mac/Linux/Android/IOS平台,具有广泛的适用性。
2、HyperLPR3安装
2.1 Github地址
HyperLPR- 基于深度学习高性能中文车牌识别
2.2 快速安装
pip install hyperlpr3
2.3 支持的车牌类别
- 单行蓝牌
- 单行黄牌
- 新能源车牌
- 教练车牌
- 白色警用车牌
- 使馆/港澳车牌
- 双层黄牌
- 武警车牌
3、代码
Github里可以下载各类语言的demo,也有开放的接口可以直接线上检测车牌。我这里基于官方demo写了一份图片和视频的车牌识别代码。
3.1 辅助函数
def draw_plate_on_image(img, box1, text1, font):
x1, y1, x2, y2 = box1 # 识别框的四至范围
# random_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2, cv2.LINE_AA) # 车牌外框
# cv2.rectangle(img, (x1, y1 - 25), (x2, y1-3), (139, 139, 102), -1) # 识别文本底色
data = Image.fromarray(img) # 读取图片
draw = ImageDraw.Draw(data) # PIL绘制图片
draw.text((x1, y1 - 27), text1, (0, 0, 255), font=font) # 添加识别文本
res = np.asarray(data) # 返回叠加识别结果的图片
return res
3.2 图片识别
def license_recognition_image(path):
image = cv2.imread(path) # 读取图片
results = catcher(image) # 执行识别算法
for code, confidence, type_idx, box in results:
# [['京Q58A77', 0.9731929, 0, [150, 160, 451, 259]]]
text = f"{code} - {confidence:.2f}"
image = draw_plate_on_image(image, box, text, font=font_ch) # 绘制识别结果
cv2.imshow("License Plate Recognition(Directed By RSran)", image) # 显示检测结果
cv2.waitKey(0)
3.3 视频识别
def license_recognition_video(path):
video = cv2.VideoCapture()
video.open(path)
i = 0
while True:
i += 1
ref, image = video.read() # 组帧打开视频
if ref:
if i % 10 == 0:
results = catcher(image) # 执行识别算法
for code, confidence, type_idx, box in results:
# [['京Q58A77', 0.9731929, 0, [150, 160, 451, 259]]]
text = f"{code} - {confidence:.2f}"
image = draw_plate_on_image(image, box, text, font=font_ch) # 绘制识别结果
cv2.imshow("License Plate Recognition(Directed By RSran)", image) # 显示检测结果
if cv2.waitKey(10) & 0xFF == ord('q'):
break # 退出
else:
break
3.4 效果展示
下图为百度图片库中检索的案例,如有侵权请联系作者删除。
4、完整代码
# -*- coding: utf-8 -*-
"""
@Time : 2024/4/19 13:59
@Auth : RS迷途小书童
@File :License Plate Recognition.py
@IDE :PyCharm
@Purpose:车辆拍照识别
@Web:博客地址:https://blog.csdn.net/m0_56729804
"""
# 导入cv相关库
import cv2
import random
import warnings
import numpy as np
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
import hyperlpr3 as lpr3
def draw_plate_on_image(img, box1, text1, font):
x1, y1, x2, y2 = box1 # 识别框的四至范围
# random_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2, cv2.LINE_AA) # 车牌外框
# cv2.rectangle(img, (x1, y1 - 25), (x2, y1-3), (139, 139, 102), -1) # 识别文本底色
data = Image.fromarray(img) # 读取图片
draw = ImageDraw.Draw(data) # PIL绘制图片
draw.text((x1, y1 - 27), text1, (0, 0, 255), font=font) # 添加识别文本
res = np.asarray(data) # 返回叠加识别结果的图片
return res
def license_recognition_video(path):
video = cv2.VideoCapture()
video.open(path)
i = 0
while True:
i += 1
ref, image = video.read() # 组帧打开视频
if ref:
if i % 10 == 0:
results = catcher(image) # 执行识别算法
for code, confidence, type_idx, box in results:
# [['京Q58A77', 0.9731929, 0, [150, 160, 451, 259]]]
text = f"{code} - {confidence:.2f}"
image = draw_plate_on_image(image, box, text, font=font_ch) # 绘制识别结果
cv2.imshow("License Plate Recognition(Directed By RSran)", image) # 显示检测结果
if cv2.waitKey(10) & 0xFF == ord('q'):
break # 退出
else:
break
def license_recognition_image(path):
image = cv2.imread(path) # 读取图片
results = catcher(image) # 执行识别算法
for code, confidence, type_idx, box in results:
# [['京Q58A77', 0.9731929, 0, [150, 160, 451, 259]]]
text = f"{code} - {confidence:.2f}"
image = draw_plate_on_image(image, box, text, font=font_ch) # 绘制识别结果
cv2.imshow("License Plate Recognition(Directed By RSran)", image) # 显示检测结果
cv2.waitKey(0)
if __name__ == "__main__":
warnings.filterwarnings("ignore", message="Mean of empty slice") # 忽略“Mean of empty slice”的警告
warnings.filterwarnings("ignore", message="invalid value encountered in scalar divide")
# 忽略“invalid value encountered in scalar divide”的警告
font_ch = ImageFont.truetype("resource/font/platech.ttf", 20, 0) # 中文字体加载
catcher = lpr3.LicensePlateCatcher(detect_level=lpr3.DETECT_LEVEL_HIGH) # 实例化识别对象
file = r"Y:\2024-04-19 14-49-09.mp4"
license_recognition_video(file)