【案例共创】基于华为云车牌识别服务设计的停车场计费系统

本案例由DS小龙哥提供

1 概述

1.1 背景介绍

车牌识别技术作为智能停车场的重要管理组成部分,得到了广泛的应用。通过自动识别车辆的车牌信息,可以实现车辆的快速进出场记录与管理,有效减少人工干预,提高效率。结合云计算技术,车牌识别系统可以进一步实现数据的集中处理和管理,为停车场的计费、安防等功能提供强大的技术支撑。

通过实际操作,让大家深入了解如何利用华为云已有的服务进行调用,可以使开发者更加熟练的调用华为云相关的服务。

1.2 适用对象

  • 个人开发者
  • 高校学生

1.3 案例时间

本案例总时长预计60分钟。

1.4 资源总览

本案例预计花费总计0元。体验完成后请及时释放资源,避免产生多余的费用。

资源名称规格单价(元)时长(分钟)
华为开发者空间 - 云主机鲲鹏通用计算增强型 kc2 | 4vCPUs | 8G | Ubuntu060

2 配置环境

2.1 开通服务

本案例中,使用云主机作为代码编写平台,并使用华为云提供的车牌识别服务为依托进行案例的开发。

下面的操作需要涉及到API接口,需要进行token进行鉴权,会使用到项目凭证这个参数。

1. 获取项目凭证点击左上角用户名,选择下拉菜单里的我的凭证。

564aef85245d8825da375992e3fcfca5.PNG

点击打开后会出现项目ID,这里需要记住,后面会用到。

6b28cd924c2f07f8f391226b12e4c589.PNG

获取token需要创建IAM子用户,将以下链接复制到浏览器。

https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users

右上角点击创建。

6aa9616878fc3980f6d70f62c023b80a.PNG

输入相关信息后点击下一步。

eb7fc098084cdb064d78971a8efd82c4.PNG

随后点击创建用户。

6aa9616878fc3980f6d70f62c023b80a.PNG

在浏览器复制以下链接开通车牌识别服务。

https://console.huaweicloud.com/ocr/?region=cn-north-4#/ocr/overview

4225b1a1e6ec854866b983db02750063.PNG

2.2 下载相关工具包

打开云主机桌面的CodeArts IDE。

0d7dc32d1722bfbd01c53a63ac2d7fd0.PNG

点击新建工程,工程名称-> number_demo,点击创建。

2.2-1.png CodeArts IDE for Python配置自动激活虚拟环境。(如果之前配置过可忽略此步骤)

选择“文件”-“设置”,在搜索框中输入“active”,在下面筛选出的结果中找到“在使用插件创建的终端中激活Python环境。”并勾选。

a758ee1ddb607dced6845d102cbd59d0.png

在CodeArts IDE for Python中打开终端,关闭命令行窗口。

3bfa2a5c6c6fe5c17b58b983ee8f485b.png

再次重新打开终端,如果命令行开头显示“(venv)”,则表示成功激活虚拟环境。

c3d80d13b1f5106748503ce6f16f5404.png

在终端输入以下命令,输入完毕后按下回车键进行下载。

pip install requests

2.2-2.png

下载完毕后继续输入以下命令:

pip3 install Pillow

9b1eb8041ec9de19749d160c07a4a86e.PNG

下载完毕后再次将以下命令复制到终端进行下载:

pip install PyQt5

86f51db721b82a9445b430b3509d95f5.PNG

继续将以下命令复制到终端中:

pip install pyqt5-tools

1eae8a6b679e582768987b7dabd08e93.PNG

3 代码编写

3.1 获取Token

Token的有效期为24小时。建议进行缓存,避免频繁调用。使用Token前请确保Token离过期有足够的时间,防止调用API的过程中Token过期导致调用API失败。重新获取Token,不影响已有Token有效性。

相关帮助文档请参考以下链接:

https://support.huaweicloud.com/api-iam/iam_30_0001.html

在CodeArts IDE中点击左上角新建文件,输入文件名-> token_demo.py。

67ecf552113287947182577a8a6e631f.PNG

将以下代码复制到文件中。

import requests
import json

# 主账号用户名
MAIN_USER = "[填你自己的]"

# IAM 子账户用户名
IAM_USER = "[填你自己的]"

# IAM 子账户密码
IAM_PASSWORD = "[填你自己的]"

# 项目 ID
PROJECT_ID = "[填你自己的]"

# 服务器区域代号
SERVER_ID = "cn-north-4"

# 保存 TOKEN 的文件路径
TOKEN_FILE_PATH = "token.txt"

def get_token():
    """
    功能: 获取 TOKEN 并保存到本地文件
    """
    # 请求地址
    request_url = f"https://iam.{SERVER_ID}.myhuaweicloud.com/v3/auth/tokens"

    # 构造请求头
    headers = {
        "Content-Type": "application/json;charset=UTF-8"
    }

    # 构造请求体
    payload = {
        "auth": {
            "identity": {
                "methods": ["password"],
                "password": {
                    "user": {
                        "domain": {
                            "name": MAIN_USER
                        },
                        "name": IAM_USER,
                        "password": IAM_PASSWORD
                    }
                }
            },
            "scope": {
                "project": {
                    "name": SERVER_ID
                }
            }
        }
    }

    # 发出 POST 请求
    try:
        response = requests.post(request_url, headers=headers, data=json.dumps(payload))

        # 打印状态码
        print(f"状态码: {response.status_code}")

        if response.status_code == 201:
            # 读取 X-Subject-Token 响应头
            token = response.headers.get("X-Subject-Token")

            # 打印返回的数据和 Token
            print(f"反馈的数据: {response.json()}")
            print(f"Token: {token}")

            # 保存 TOKEN 到本地文件
            if token:
                save_token_to_file(token)
                print(f"TOKEN 已保存到 {TOKEN_FILE_PATH}")
            else:
                print("未能获取到 TOKEN")
        else:
            print(f"获取 TOKEN 失败: {response.text}")

    except Exception as e:
        print(f"请求发生错误: {e}")

def save_token_to_file(token):
    """
    保存 TOKEN 到本地文件
    """
    try:
        with open(TOKEN_FILE_PATH, "w") as file:
            file.write(token)
    except Exception as e:
        print(f"保存 TOKEN 时发生错误: {e}")

def main():
    # 获取 TOKEN
    get_token()

if __name__ == "__main__":
    main()
需要替换部分为:
# 主账号用户名
MAIN_USER = "[填你自己的]"

# IAM 子账户用户名
IAM_USER = "[填你自己的]"

# IAM 子账户密码
IAM_PASSWORD = "[填你自己的]"

# 项目 ID
PROJECT_ID = "[填你自己的]"

将代码中相应的部分进行替换,替换完毕后鼠标右击运行。

3a1a2090d337e89c9e6e1ad58e1539d3.PNG

运行成功后会提示,token已保存到token.txt。

43598455fe5464946543f88927970072.PNG

3.2 车牌识别代码编写

再次点击左上角新建文件,命名->car_number.py。

a7e997eade2e6d079d0a3d534f0efd95.PNG

将以下代码复制到文件中:

import sys
import base64
import requests
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QFileDialog, QTextEdit
)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
# 从文件中读取Token
def read_token():
    try:
        with open("token.txt", "r") as file:
            token = file.read().strip()
        return token
    except FileNotFoundError:
        print("Error: token.txt file not found!")
        return None
# 将图片转换为Base64编码
def image_to_base64(image_path):
    try:
        with open(image_path, "rb") as image_file:
            base64_image = base64.b64encode(image_file.read()).decode("utf-8")
        return base64_image
    except FileNotFoundError:
        print(f"Error: Image file {image_path} not found!")
        return None
# 车牌识别函数
def recognize_license_plate(image_path):
SERVER_ID = "cn-north-4"
项目ID替换为自己的项目ID
    PROJECT_ID = "替换为自己的项目ID"
    token = read_token()

    if not token:
        return "错误:无法读取Token文件。"

    # 设置请求地址
    request_url = f"https://ocr.{SERVER_ID}.myhuaweicloud.com/v2/{PROJECT_ID}/ocr/license-plate"

    # 编码图片
    img_data = image_to_base64(image_path)
    if not img_data:
        return "错误:无法对图片进行Base64编码。"

    # 构造请求头
    headers = {
        "Content-Type": "application/json;charset=UTF-8",
        "X-Auth-Token": token
    }

    # 构造请求参数
    payload = {
        "image": img_data
    }

    # 发送POST请求
    try:
        response = requests.post(request_url, json=payload, headers=headers)

        # 处理响应
        if response.status_code == 200:
            return response.json()
        else:
            return f"请求失败,状态码:{response.status_code}\n响应内容:{response.text}"
    except requests.RequestException as e:
        return f"请求过程中发生错误:{e}"
# 主窗口类
class LicensePlateRecognizer(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("车牌识别")
        self.setGeometry(100, 100, 800, 600)

        # 创建主布局
        main_layout = QHBoxLayout()

        # 左侧布局:显示图片
        self.image_label = QLabel("未加载图片")
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setStyleSheet("border: 1px solid black;")
        self.image_label.setFixedSize(300, 400)
        main_layout.addWidget(self.image_label)

        # 中间布局:按钮
        button_layout = QVBoxLayout()
        self.load_button = QPushButton("加载图片")
        self.load_button.clicked.connect(self.load_image)
        button_layout.addWidget(self.load_button)

        self.recognize_button = QPushButton("识别车牌")
        self.recognize_button.clicked.connect(self.recognize_image)
        button_layout.addWidget(self.recognize_button)

        button_layout.addStretch()
        main_layout.addLayout(button_layout)

        # 右侧布局:显示结果
        self.result_text = QTextEdit()
        self.result_text.setReadOnly(True)
        self.result_text.setStyleSheet("border: 1px solid black;")
        main_layout.addWidget(self.result_text)

        # 设置中央窗口
        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        self.image_path = None  # 存储加载的图片路径

    # 加载图片
    def load_image(self):
        options = QFileDialog.Options()
        file_path, _ = QFileDialog.getOpenFileName(self, "打开图片文件", "", "图片文件 (*.png *.jpg *.jpeg)", options=options)

        if file_path:
            self.image_path = file_path
            pixmap = QPixmap(file_path)
            scaled_pixmap = pixmap.scaled(300, 400, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.image_label.setPixmap(scaled_pixmap)
            self.result_text.setText("")  # 清空上次的结果
        else:
            self.image_label.setText("未加载图片")

    # 识别车牌
    def recognize_image(self):
        if not self.image_path:
            self.result_text.setText("错误:未加载图片!")
            return

        self.result_text.setText("识别中...")
        result = recognize_license_plate(self.image_path)

        # 提取并显示结果
        if isinstance(result, dict) and "result" in result:
            try:
                plate_number = result["result"][0]["plate_number"]
                plate_color = result["result"][0]["plate_color"]
                self.result_text.setText(f"车牌号码:{plate_number}\n车牌颜色:{plate_color}")
            except (IndexError, KeyError):
                self.result_text.setText("错误:未能正确解析返回的结果。")
        else:
            self.result_text.setText(str(result))
# 主程序入口
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = LicensePlateRecognizer()
    window.show()
    sys.exit(app.exec_())

涉及到的地址需要自行前往网上下载,下载完毕后,将图片放到与代码文件同一级目录下即可。

需要修改的地址,这里将None修改为需要识别的图片路径。

self.image_path = None \# 存储加载的图片路径

2efd8ef30b23b2c6680cecbff0396589.PNG

图片下载完毕后点击运行,点击加载车牌,将所需要识别的上传上去,再点击识别车牌。

bcfb997360685dcbfad385bec25dc1d7.PNG

至此,实验结束。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值