使用Streamlit构建一个车牌识别应用程序

使用Streamlit搭建车牌识别应用程序

摘要

本文简要介绍了使用预训练模型从可变行车牌中提取文本的解决方案,并详细解释了如何使用Streamlit构建Web应用程序,将此解决方案提供给用户 逐步操作。

Streamlit是一个专门为机器学习和数据科学项目构建的开源应用程序框架。

目标受众

  • 对学习网页开发感兴趣,但认为学习HTML、CSS、JS需要花费太多时间的数据科学家。
  • 有志于将Python代码转化为可共享Web应用程序的机器学习工程师。

大纲

  1. 检测离相机最近的车牌
  2. 使用easyocrtesseract 提取文本
  3. 构建一个应用程序,以图片作为输入,然后输出一个字符串

问题陈述

给定来自不同角度、距离和光照条件的一辆或多辆车的二维图像,我们想要提取离相机最近的车辆的车牌号码。所有车牌都来自新加坡,因此车牌号码只包含英文字符和数字,长度可变,具有一到两行。

来源:您在Executive Traveller上发布的新加坡出租车指南。
  1. 检测离相机最近的车牌

我将使用一个没有进行精调的预训练yolov5模型,因为我没有数据。这是我的代码:

import yolov5import torchdef inference(    path2img: str,    show_img: bool = False,    size_img: int = 640,    nms_conf_thresh: float = 0.7,    max_detect: int = 10,) -> torch.Tensor:    model = yolov5.load("keremberke/yolov5m-license-plate")    model.conf = nms_conf_thresh    model.iou = 0.45    model.agnostic = False    model.multi_label = False    model.max_det = max_detect    results = model(path2img, size=size_img)    results = model(path2img, augment=True)    if show_img:        results.show()    return results.pred[0]

我知道你一定想知道为什么我不直接将max_detect设置为1,并直接获取一个边界框,而不是多个?这是因为每个预测的边界框都有一个置信度分数。使用max_detect = 1,您将获得置信度最高的预测结果,但这并不总是指示离相机最近的车牌。

使用预训练的yolov5模型检测所有车牌。

因此,我必须计算所有预测边界框的区域,并保留面积最大的那个。这将始终给我提供离相机最近的车牌,即使置信度由于倾斜角等原因较低。

获取离相机最近的车牌。

2. 使用 easyocr tesseract 提取文本

如果您的车牌长度固定且只有一行,tesseract基本上就足够了。然而,根据我的经验,它在数字9和字符Z上表现较差,并且偶尔也会出现字母D的识别错误。

以下是我的代码。如果您的车牌包含非英文字符,请相应地更改tessedit_char_whitelistlang

import pytesseractdef ocr_tesseract(path2img):    text = pytesseract.image_to_string(        path2img,        lang="eng",        config="--oem 3 --psm 6 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",    )    return text

它可以成功识别单行车牌号码,但是对于下面这个图像,tesseract无法提取第二行。

Source: Toyota Wish Taxi in Singapore 23.9.2017 2926 taken by Elmar

这个红色出租车车牌对于tesseract来说相当困难,因为它包含字母D、数字9和字符Z。我们来试试easyocr吧!

easyocr检测输出

尽管有一些挑战,easyocr成功识别了大多数字符,除了数字5!我绝对推荐使用easyocr而不是tesseract。以下是我的代码:

def ocr_easyocr(path2img):    image = cv2.imread(path2img)    reader = easyocr.Reader(["en"], gpu=False)    detections = reader.readtext(image)    plate_no = []    [plate_no.append(line[1]) for line in detections]    return "".join(plate_no)

3. 构建一个应用程序,接受图像作为输入,并输出一个字符串

现在是最令人兴奋的部分!

为了让用户能够使用我们建立的功能,我们需要一个Web应用程序来上传图像并读取解码后的车牌字符串。

更具体地分解如下:

  • 3.1 显示标题和副标题
  • 3.2 显示文件上传器,供用户上传图像
  • 3.3 以文本输出形式显示识别出的车牌号码
  • 3.4 显示上传的图像和预测的边界框

3.1 显示标题和副标题

首先,让我们通过在终端中运行pip install streamlit来安装streamlit

接下来,通过在终端中运行streamlit hello来打开Streamlit UI。

UI将在默认浏览器中弹出。尽情享受探索这个演示吧!

3.2 显示文件上传器,供用户上传图像

现在,让我们给我们的Web应用添加一个标题。我在src/中创建了一个名为app.py的Python脚本。

import streamlit as stdef app():    st.header("车牌识别网页应用")    st.subheader("由YOLOv5提供技术支持")    st.write("欢迎!")if __name__ == "__main__":    app()

然后我在终端中运行了命令streamlit run src/app.py

在网页应用中运行`streamlit run <path>`以查看变化。

刷新网页,你会看到标题和副标题出现在那里!你完全不需要使用HTML语法!

标题出现在streamlit网页应用中。

是时候添加更多小部件了!我想要一个带有按钮的文件上传器,供用户点击使用。下面是新的app函数。

def app():    st.header("车牌识别网页应用")    st.subheader("由YOLOv5提供技术支持")    st.write("欢迎!")    # 添加文件上传器    with st.form("my_uploader"):        uploaded_file = st.file_uploader(            "上传图像", type=["png", "jpg", "jpeg"], accept_multiple_files=False        )        submit = st.form_submit_button(label="上传")

再次运行streamlit run命令,你将看到文件上传器出现。你完全不需要任何css样式。

已添加文件上传器。

3.3 将识别出的车牌号显示为文本输出

一旦用户上传一张图像(触发方式:点击上传按钮),我们可以使用相关的Python函数进行推理。车牌号将以文本形式显示。

def app():    st.header("车牌识别网页应用")    st.subheader("由YOLOv5提供技术支持")    st.write("欢迎!")    with st.form("my_uploader"):        uploaded_file = st.file_uploader(            "上传图像", type=["png", "jpg", "jpeg"], accept_multiple_files=False        )        submit = st.form_submit_button(label="上传")    if uploaded_file is not None:        # 保存上传的图像        save_path = os.path.join("temp", uploaded_file.name)        with open(save_path, "wb") as f:            f.write(uploaded_file.getbuffer())    if submit:        # 以文本形式显示车牌号        text = run_license_plate_recognition(save_path).recognize_text()        st.write(f"检测到的车牌号码:{text}")if __name__ == "__main__":    app()
将提取的车牌号码以文本形式显示。

3.4 显示上传的图像与预测的边界框

尽管在网页应用中有输入和输出,但这还不够。如果我们能够显示用户上传的图像并标注边界框,将会更好。通过添加一个小部件,我们可以向用户展示预测是针对正确的车辆进行的。特别是当预测不完美时,用户可以更容易地发现差异。

来源:Dinesh Dayani的《新加坡出租车乘车费率和票价的完全指南》

为了使其更加交互,我将在处理请求时添加一个旋转器。

已添加旋转器。

一旦检测完成,图像将显示在下方。

车牌识别 Web 应用看起来很棒!

在使用 Django 之后,我真的很喜欢 Streamlit。后者并非是数据科学家可以一天掌握的东西。Streamlit 可以让数据科学家专注于我们的工作,同时又能够在没有前端 Web 开发知识的情况下向用户部署解决方案。

要查看代码存储库,请点击此链接。

在 LinkedIn 上关注我 | 为我的故事点赞 | 在 VoAGI 上关注我