基于python编写的车牌识别系统

总体功能概述

该程序通过 摄像头实时采集视频帧,利用 OpenCV 的 Haar Cascade 模型 检测车牌区域,
然后用 HyperLPR3 识别出车牌号。识别结果会在视频画面上实时显示,并且高亮显示车牌位置。

它具有以下特性:

  • ✅ 自动识别并修复中文路径问题(模型文件无法加载的常见错误)

  • ✅ 支持中文字体显示(通过 platech.ttf

  • ✅ 实时摄像头捕获与识别

  • 自动路径修复能自动识别中文目录并将模型复制到英文临时目录,彻底解决加载失败问题。
    实时识别使用 OpenCV 实时检测车牌,HyperLPR3 进行车牌识别。
    中文输出支持中文车牌号显示,不乱码。
    稳定可靠各关键点都有错误检测与提示,防止程序崩溃。
    视觉友好半透明矩形与小预览窗口让识别结果一目了然。

     

  • 程序启动 → 自动切换工作目录

  • 检查并加载模型文件(复制到英文临时路径)

  • 打开摄像头并设置参数

  • 循环读取每一帧图像:

    • 检测车牌位置

    • 调用 HyperLPR3 识别车牌

    • 绘制车牌框、显示识别结果

  • 按下 Q 键退出运行后效果,运行后效果。

代码:

import cv2
import hyperlpr3 as lpr3
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import os
import shutil
import tempfile
import sys

# === 自动切换工作目录为脚本所在目录 ===
os.chdir(os.path.dirname(os.path.abspath(__file__)))

# === 车牌检测模型路径 ===
cascade_filename = 'haarcascade_russian_plate_number.xml'
src_cascade_path = os.path.join(os.getcwd(), cascade_filename)

# 检查模型文件是否存在
if not os.path.exists(src_cascade_path):
    print(f"❌ 没有找到模型文件: {src_cascade_path}")
    sys.exit(1)

# === 如果路径中含有中文,复制到系统临时目录(纯英文路径) ===
if any('\u4e00' <= ch <= '\u9fff' for ch in src_cascade_path):
    tmp_cascade_path = os.path.join(tempfile.gettempdir(), cascade_filename)
    shutil.copy(src_cascade_path, tmp_cascade_path)
    print(f"⚙️ 检测到中文路径,已复制模型到临时目录: {tmp_cascade_path}")
    cascade_path = tmp_cascade_path
else:
    cascade_path = src_cascade_path

# === 加载 Haar 模型 ===
plateCascade = cv2.CascadeClassifier(cascade_path)
if plateCascade.empty():
    print(f"❌ 无法加载分类器文件: {cascade_path}")
    sys.exit(1)
else:
    print("✅ 成功加载车牌检测模型!")

# === 初始化车牌识别器 ===
catcher = lpr3.LicensePlateCatcher()

# === 摄像头设置 ===
frameWidth, frameHeight = 640, 480
minArea = 500
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, frameWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frameHeight)
cap.set(cv2.CAP_PROP_EXPOSURE, 0.1)
cap.set(cv2.CAP_PROP_GAIN, 0.1)
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0)

# === 字体路径(中文显示) ===
font_path = "C:/Users/Administrator/Desktop/python/fonts/platech.ttf"
font_size = 20
chinese_font = ImageFont.truetype(font_path, font_size)

# === 初始化变量 ===
prev_plate_info = ""
snapshot = None
plate_info_x, plate_info_y = 0, 0
plate_info_width, plate_info_height = 450, 30
rect_thickness = -1
rect_color = (0, 0, 255)
rect_opacity = 0.5
tracked_plate_position = None

print("🚗 车牌识别系统启动中... 按 Q 键退出")

# === 主循环 ===
while True:
    success, img = cap.read()
    if not success:
        print("⚠️ 无法读取摄像头,请检查设备连接。")
        break

    imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    numberPlates = plateCascade.detectMultiScale(imgGray, 1.1, 4)
    plate_info_str = prev_plate_info

    for (x, y, w, h) in numberPlates:
        area = w * h
        if area > minArea:
            plate_info = catcher(img[y:y + h, x:x + w])
            if plate_info:
                plate_info_str = str(plate_info[0])
                prev_plate_info = plate_info_str
                plate_img = img[y:y + h, x:x + w]
                snapshot = cv2.resize(plate_img, (180, 100))
                tracked_plate_position = (x, y, w, h)

    if tracked_plate_position is not None:
        x, y, w, h = tracked_plate_position
        overlay = img.copy()
        cv2.rectangle(overlay, (x, y), (x + w, y + h), rect_color, rect_thickness)
        cv2.addWeighted(overlay, rect_opacity, img, 1 - rect_opacity, 0, img)

    pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(pil_img)
    draw.rectangle([(plate_info_x, plate_info_y),
                    (plate_info_x + plate_info_width, plate_info_y + plate_info_height)],
                   fill="black")
    draw.text((plate_info_x + 5, plate_info_y + 5), plate_info_str, font=chinese_font, fill="red")
    img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

    if snapshot is not None:
        img[10:110, frameWidth - 190:frameWidth - 10] = snapshot

    cv2.imshow("Result", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
模型文件:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_russian_plate_number.xml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BG8EQB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值