完整的设计思路、界面截图、识别效果对比,请参见项目根目录下的演示文档:
📄 具体思路与成果讲解.pdf —— 包含全部成果页面展示(点击下载查看)
| 模块 | 功能 |
|---|---|
| 🔍车牌识别 | EasyOCR 定位 + OpenCV 字符分割 + CNN 分类,三级流水线 |
| 🎥实时监控 | 摄像头实时画面 + 自动检测车牌 + 连续 2 秒确认自动入库 |
| 💰智能计费 | 按分钟 / 按半小时两种模式,支持免费时长、单日封顶 |
| 👥角色管理 | 管理员(监控 / 报表 / 用户管理)和普通用户(记录查询) |
| 📊报表导出 | 停车记录一键导出为 Excel,含时长和费用统计 |
| 🗄️双模存储 | MySQL + JSON 自动降级,没有数据库也能直接跑 |
深度学习 PyTorch · EasyOCR · OpenCV · NumPy
GUI 框架 PyQt5 · QSS 样式表
数据存储 MySQL · JSON(自动降级)
导出工具 Pandas · OpenPyXL
ParkingSystem/
├── main.py # 🚀 程序入口
├── config.py # ⚙️ 配置(计费规则、路径、数据库)
├── requirements.txt # 📦 依赖列表
├── 具体思路与成果讲解.pdf # 📄 设计思路与界面截图
├── core/ # 🧠 核心业务逻辑
│ ├── recognition.py # 车牌定位 → 字符分割 → CNN 识别
│ ├── billing.py # 计费引擎(按分钟 / 按单位)
│ ├── camera.py # 摄像头管理(PyQt 信号驱动)
│ └── test_single.py # 单张图片测试脚本
├── models/ # 🤖 深度学习模型
│ ├── model.py # SimpleCNN(3 层卷积)
│ └── best_cnn_model.pth # 预训练权重(2.4 MB)
├── ui/ # 🖥️ 图形界面
│ ├── login_window.py # 登录窗口(背景图 + 半透明面板)
│ ├── admin_window.py # 管理员主界面
│ ├── monitor_window.py # 实时监控 + 识别窗口
│ └── user_window.py # 用户查询窗口
├── database/ # 💾 数据访问层
│ └── db.py # MySQL / JSON 双模存储
├── utils/ # 🛠️ 工具
│ ├── excel_export.py # Excel 报表导出
│ └── style.qss # 全局 QSS 样式表
└── data/ # 📂 运行时数据
├── users.json.example # 用户配置模板
├── records/ # 进出场记录
└── reports/ # 导出报表
- Python
3.8及以上- 操作系统 Windows / Linux / macOS
- MySQL
5.7+(可选 —— 不装也能跑,系统自动降级为 JSON 模式)
git clone https://github.com/simodai/ParkingSystem.git
cd ParkingSystempython -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux / macOS
pip install -r requirements.txt
⚠️ 跳过此步骤也能直接运行 —— 系统使用纯 JSON 文件存储,无需 MySQL。
如需启用 MySQL:
Windows PowerShell
$env:DB_HOST = "localhost"
$env:DB_PORT = "3306"
$env:DB_USER = "root"
$env:DB_PASSWORD = "你的密码"
$env:DB_NAME = "db_parking"Linux / macOS
export DB_HOST=localhost
export DB_PORT=3306
export DB_USER=root
export DB_PASSWORD=你的密码
export DB_NAME=db_parkingpython main.py💡 首次运行时 EasyOCR 会自动下载约 100 MB 的识别模型到
models/easyocr_models/,请耐心等待。
| 账号 | 密码 | 角色 | 权限 |
|---|---|---|---|
admin |
123 |
🔧 管理员 | 实时监控 · 数据报表 · 用户管理 |
user |
123 |
👤 普通用户 | 停车记录查询与筛选 |
首次运行会自动创建
data/users.json,无需手动配置。
# 使用项目内默认测试图片
python core/test_single.py
# 指定自定义图片路径
python core/test_single.py /path/to/your_car_image.jpg| 文件 | 说明 |
|---|---|
ui/login_window.py |
登录窗口,支持背景图片 + 半透明毛玻璃面板,连续输错 3 次锁定 |
ui/admin_window.py |
管理员主界面,实时刷新停车记录、一键导出 Excel、用户增删改 |
ui/monitor_window.py |
摄像头监控画面 + 车牌自动识别 + 连续 2 秒确认入库 |
ui/user_window.py |
普通用户界面,按车牌号 / 日期筛选个人停车记录 |
摄像头帧 → EasyOCR 文本检测定位车牌 → OpenCV 二值化 + 轮廓分割字符
→ 保持比例缩放 + 黑色填充 → SimpleCNN 单字符分类 → 输出车牌号
| 文件 | 职责 |
|---|---|
core/recognition.py |
EasyOCR 定位 → 图像预处理 → 字符分割(含 NMS 去重叠、边缘噪声过滤) |
models/model.py |
3 层卷积 + 全连接分类器,支持 0-9 A-F 共 16 类字符 |
core/billing.py |
按分钟 / 按半小时计费,支持免费时长(默认 15 分钟)和单日封顶 |
core/camera.py |
基于 PyQt QTimer 的摄像头帧捕获,通过 pyqtSignal 推送帧 |
| 模式 | 触发条件 | 说明 |
|---|---|---|
| MySQL | 检测到 pymysql 且连接成功 |
用户表 + 停车记录表,自动建表 |
| JSON (降级) | MySQL 不可用 | 自动读写 data/users.json + data/records.json,无缝切换 |
在开发过程中,针对字符分割与识别准确率的问题,经历了 4 次关键迭代:
| 现象 | 原因 | 解决 |
|---|---|---|
| 分割正确但识别错误 | 粗暴 resize(32, 32) 把瘦长的 "1" 横向拉宽 |
保持长宽比缩放 + 黑色填充 |
# ❌ 旧代码:强制拉伸变形
roi = cv2.resize(roi, (32, 32))
# ✅ 新代码:保持比例 + 填充
h, w = roi.shape
scale = min(28 / h, 28 / w)
resized = cv2.resize(roi, (int(w * scale), int(h * scale)))
padded = cv2.copyMakeBorder(resized, top, bottom, left, right,
cv2.BORDER_CONSTANT, value=0)| 现象 | 原因 | 解决 |
|---|---|---|
| 结果多出一个 "A" | 字符边缘阴影产生重叠轮廓框 | NMS 去重叠,IoU > 50% 保留大框 |
overlap_x = max(0, min(px + pw, x1 + w1) - max(px, x1))
if overlap_x > w1 * 0.5:
if w1 * h1 > pw * ph:
filtered_boxes.pop()
filtered_boxes.append(box)| 现象 | 原因 | 解决 |
|---|---|---|
| 车牌黑框线被当字符 | EasyOCR 定位框偏大包含边框 | 过滤靠边 + 极瘦的物体 |
if x < 7 or (x + cw) > w_plate - 7: continue
is_at_edge = (x < w_plate * 0.20) or (x + cw > w_plate * 0.80)
is_too_thin = (cw < median_w * 0.60)
if is_at_edge and is_too_thin: continue| 现象 | 原因 | 解决 |
|---|---|---|
| "1" 被误当边框过滤 | 边缘范围 20%、宽度阈值 60% 过高 | 回调参数找平衡点 |
# ✅ 最终版:边缘范围缩小到 12%,宽度阈值降到 35%
if x < 5 or (x + cw) > w_plate - 5: continue
is_at_edge = (x < w_plate * 0.12) or (x + cw > w_plate * 0.88)
is_too_thin = (cw < median_w * 0.35)
if is_at_edge and is_too_thin: continue📄 更多设计细节与界面截图请查看 具体思路与成果讲解.pdf(点击下载查看)
本项目为课程实验项目,仅供学习交流使用。