尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Mask R-CNN结合char_cnn的停车场车牌识别系统设计与实践
简介基于Mask R-CNN训练模型与PyQt开发的车牌识别系统完整项目源码面向人工智能、通信工程、自动化、电子信息等专业的在校生和开发者适用于毕业设计、课程设计或项目初期演示。项目包含可运行的图形界面、模型权重、车牌数据集与标注文件并配有停车场出入库演示视频能够直观展示从识别到交互操作的全流程帮助使用者快速掌握深度学习模型与桌面端应用结合的实际开发思路。压缩包共291个文件以247张jpg车牌样本图片为主配合26个py源码文件、5个json标注文件、4个ui界面文件以及avi场景录屏、h5模型权重、说明文档等整体大小67.54MB目录层级清晰便于分模块查阅和学习。目前已有48人学习下载代码均测试运行成功已获导师指导认可答辩评分达95分。除完整源码与文档外还附带了停车管理相关辅助文件可直接用于课设、毕设或在此基础上进行二次功能扩展。1. Mask R-CNN 车牌识别系统停车场场景下的模型选型与工程落地在停车场出入口场景里车牌识别不是“拍一张照片然后 OCR”那么简单真正的难点在于定位和分段识别车牌在画面里可能倾斜、反光、被挡传统轮廓检测在这种场景下误检率居高不下。这套基于 Mask R-CNN PyQt 的车牌识别系统把检测环节交给实例分割模型用 char_cnn 完成字符识别再通过 PyQt 把入库、出库、记录查询串成一个完整管理系统。源码包里除了模型权重 char_cnn.h5还附带入库.avi、出库.avi 两段真实场景视频和几张带车牌号的测试图沪KT5583、沪JS6999、浙E6686V 等适合正在做课设、毕设或者想了解“检测识别界面”全链路怎么拼起来的人。2. Mask R-CNN 车牌检测模型训练从标注到权重生成2.1 车牌数据标注从单张样板图到 COCO 格式Mask R-CNN 的训练数据标注建议直接转成 COCO 格式因为后续无论用 Matterport 版 Mask_RCNN 还是 mmdetection都能无缝切换。源码包里提供了沪KT5583.jpg、浙AM690M.jpg 这类样张其中沪KT5583.jpg 是典型的高位俯拍图车牌区域比例适中适合做第一张标注样板。标注的核心是给“车牌”区域画多边形而不是画矩形框。虽然 Mask R-CNN 也输出 bbox但训练时用的 ground truth 是分割掩码多边形标注能保留车牌边界的真实形状对倾斜车牌尤其重要。一个完整标注项长这样{ images: [ { id: 1, file_name: 沪KT5583.jpg, width: 1920, height: 1080 } ], annotations: [ { id: 1, image_id: 1, category_id: 1, segmentation: [ [1024, 512, 1280, 514, 1278, 594, 1026, 590] ], bbox: [1024, 512, 256, 80], area: 20480 } ], categories: [ { id: 1, name: plate } ] }segmentation 里的坐标是多边形顶点标注工具一般导出成这种格式bbox 是外接矩形area 是多边形面积。训练 Mask R-CNN 时area会被用来计算 RoI 的尺度分配写错了会影响小目标召回率因此从标注工具导出后最好校验一遍。实际标注建议至少准备 200 到 300 张图。如果只有几张样板图另一个常见做法是先用预训练模型在视频帧上跑一遍把置信度高的检测结果保存下来人工修一下错误掩码再回填训练集。这种方式能把标注成本压缩一半以上。2.2 训练参数配置与 loss 收敛观察以 Matterport 的 Mask_RCNN 为例训练配置集中在 config 类里。这套系统场景是固定机位的停车场出入口所以输入分辨率不用太大IMAGE_MIN_DIM设为 512 就够了太高会增加显存压力还容易把远处无关车牌框进来。import mrcnn.config class PlateConfig(mrcnn.config.Config): NAME plate GPU_COUNT 1 IMAGES_PER_GPU 1 NUM_CLASSES 1 1 # 背景 车牌 STEPS_PER_EPOCH 200 VALIDATION_STEPS 50 DETECTION_MIN_CONFIDENCE 0.7 RPN_ANCHOR_SCALES (32, 64, 128, 256, 512) IMAGE_MIN_DIM 512 IMAGE_MAX_DIM 1024RPN_ANCHOR_SCALES决定了候选框的尺度分布。车牌在 1080p 画面里宽度大约占 15% 到 30%换算到 1024 分辨率下就是 150 到 300 像素所以 anchor 里必须有 256 这个档位只留小尺度会漏检较近的车牌全用大尺度又会把整辆车包进去。DETECTION_MIN_CONFIDENCE在训练阶段不影响 loss但会影响验证时输出的检测框数量调试阶段设成 0.7 能减少展示噪点。训练命令常见写法是python train.py --config plate --dataset ./plate_dataset --weights coco用 COCO 预训练权重做迁移学习时建议第一段训练冻结 backbone 的 head 和 FPN 之后的网络只训练新加的类别层跑 20 个 epoch 后再解冻全部层把学习率降到 0.001 继续训练。观察训练日志时重点看rpn_bbox_loss和mrcnn_mask_loss两条曲线如果 mask loss 在 0.1 到 0.2 之间徘徊但 bbox loss 一直降不下来优先检查标注多边形是否贴合车牌边缘其次检查 anchor 尺度。2.3 模型导出与检测效果验证训练结束后除了保存mask_rcnn_plate.h5之外还需要单独导出推理用的模型结构因为 PyQt 端不会引入整个训练框架。常见做法是把model实例的keras_Model部分序列化model.keras_model.save(plate_inference.h5)这一步的好处是去掉训练分支RPN target、mask target 等推理时只保留 backbone FPN RPN head detection head。在源码包里没有直接看到 mask_rcnn 权重文件只有 char_cnn.h5说明该项目在交付时可能把 maskrcnn 的权重作为“训练产物”留给用户自行生成或者训练好的检测模型整合进了主程序。如果你准备换用自己的训练权重注意plate_inference.h5和char_cnn.h5是两套独立的模型前者输出车牌区域掩码和 bbox后者负责识别字符。验证检测效果时用视频比用单帧更可靠。把入库.avi 的第一帧抽出来跑推理然后检查两个指标一是 bbox 是否稳定覆盖整个车牌二是 mask 是否只包含车牌区域而不包含车灯或保险杠。如果出现 mask 泄漏到保险杠上说明训练数据里缺少“车牌 部分车头”的负样本边界可以在标注时把车牌边缘往里缩 2 到 3 个像素。3. char_cnn.h5 车牌字符识别分割、识别与规则纠错3.1 字符分割的投影法与连通域取舍Mask R-CNN 输出的是车牌区域但真正要识别的内容是车牌上的汉字、字母和数字。常见做法是先把掩码对应的图像做透视矫正把车牌子图像统一拉正成固定宽高比再做字符分割。分割方法上传统投影法在干净背景下很有效把二值化图像沿水平方向做像素投影波谷位置就是字符间隙。但停车场夜间场景下车牌边框的铆钉、国徽标记会产生很多伪波谷所以我更倾向于用连通域分析筛选候选字符区域。写一个简化的分割逻辑import cv2 import numpy as np def split_plate_chars(plate_img): gray cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY) # 自适应阈值避免夜间反光导致整块白化 binary cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 31, 10) # 去掉小噪点 kernel np.ones((3, 3), np.uint8) binary cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) contours, _ cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) plate_h, plate_w gray.shape char_boxes [] for cnt in contours: x, y, w, h cv2.boundingRect(cnt) # 车牌字符的宽高比大约在 0.2~0.8 之间 if h plate_h * 0.3 and 0.15 w / h 0.9: char_boxes.append((x, y, w, h)) char_boxes.sort(keylambda b: b[0]) return char_boxesadaptiveThreshold的 blockSize 设为 31光源不均匀时比固定阈值稳定MORPH_CLOSE能把汉字内部断裂的笔画连起来避免一个“沪”字被拆成三四个连通域。排序用x坐标保证最后输出的字符顺序是从左到右。如果分割结果总是多出一个左边框区域可以在findContours前用cv2.bitwise_and结合车牌掩码把边框外的像素抹掉。3.2 char_cnn 结构解析与推理调用源码里的char_cnn.h5是训练好的字符分类模型输入通常是固定尺寸的灰度图输出是字符类别概率。对于中国车牌类别空间包括 31 个省份汉字京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云陕甘青宁新、24 个字母I 和 O 不用以及 10 个数字总共约 65 类。如果数据集里没有汉字类别模型就只能识别字母数字这会导致“沪”字被误判。直接用 Keras 加载权重做推理from keras.models import load_model import cv2 import numpy as np char_model load_model(char_cnn.h5) def recognize_chars(char_images): results [] for img in char_images: img cv2.resize(img, (32, 32)) img img.astype(np.float32) / 255.0 img np.expand_dims(img, axis-1) # 若是单通道 img np.expand_dims(img, axis0) pred char_model.predict(img)[0] cls_id int(np.argmax(pred)) conf float(pred[cls_id]) results.append((idx_to_char(cls_id), conf)) return resultsidx_to_char对应训练时保存的类别索引表这个表必须在训练时就固定下来否则推理时类别错位。另外char_cnn.h5这个文件名暗示模型是纯 CNN 而非 LSTMCTC所以它对字符之间粘连的容忍度较低如果实际识别时出现“浙E6686V”被分成“浙 E 66 86 V”这种连续数字合并的情况需要把分割阈值的w/h上限放宽到 1.2并额外做一次“过分割后拼接”的尝试。字符识别置信度也可以当作分割质量的反馈信号。比如某字符置信度低于 0.5常见原因是分割窗口把字符截掉了一半这时可以把该窗口左右各扩 20% 再识别一次取置信度更高的结果。3.3 基于先验规则的车牌合法性校验模型识别出来的结果不能直接用必须经过一个规则层。中国车牌的编码规则是第一位是省份汉字第二位是发牌机关字母后面是 5 位字母数字组合其中字母 I 和 O 通常不出现军用、警用等特殊车牌除外。这套系统面对的是民用停车场所以校验逻辑可以写得很硬位置规则示例第 1 位必须是 31 个省份汉字之一沪、浙、苏第 2 位必须是大写字母A-Z不含 I、O第 3~7 位字母数字混合不含 I、OKT5583、E6686V总长度7 个字符沪KT5583规则层的实现不建议用正则硬匹配所有组合而是先接收字符识别结果再逐个位置验证。例如第一位识别出“浙”但第二位识别出“0”就可以把第二位强制纠正为“D”或“Q”这种纠正需要谨慎最好只是标记低置信度而不是强改。对于进出场记录来说宁可拒绝本次识别让用户手动补录也不能把错误车牌写进数据库否则计费会出大问题。4. PyQt 停车场管理界面视频流、入库出库与记录联动4.1 工程入口与主界面框架源码包里的parking_roll_management_system.e4p是工程入口文件用 PyQt 开发时它定义了项目文件结构和启动配置。主界面建议拆成三个区域左侧是视频预览右侧是当前识别结果与车辆信息底部是历史记录表格。这样在一屏内就能完成“看到车来 → 识别 → 入库/出库确认”的操作闭环。一个最简的 PyQt 主窗口骨架from PyQt5.QtWidgets import QMainWindow, QLabel, QTableWidget, QVBoxLayout, QWidget class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(停车场车牌识别管理系统) self.video_label QLabel(视频预览) self.table QTableWidget(0, 5) self.table.setHorizontalHeaderLabels([时间, 方向, 车牌, 置信度, 停车时长]) layout QVBoxLayout() layout.addWidget(self.video_label) layout.addWidget(self.table) container QWidget() container.setLayout(layout) self.setCentralWidget(container)这里的QTableWidget只作演示实际数据量大了以后要换成QTableView QAbstractTableModel否则入库出库上千条记录后界面会明显卡顿。如果你拿到源码直接跑注意检查.e4p里配置的主启动文件是哪个通常是一个main.py或app.py启动前确保 PyQt5、opencv-python、keras 都装在同一个 Python 环境。4.2 视频流接入与检测线程设计PyQt 的主线程负责界面刷新绝对不能在里面跑模型推理。从入库.avi、出库.avi读取帧并做检测是一个耗时操作必须放到工作线程里。我一般用QThread循环读帧每读一帧就通过信号把画面传给主线程显示同时把检测结果通过另一个信号发送。from PyQt5.QtCore import QThread, pyqtSignal import cv2 class DetectThread(QThread): frame_ready pyqtSignal(object) result_ready pyqtSignal(str, float) def __init__(self, video_path, detector, recognizer): super().__init__() self.video_path video_path self.detector detector self.recognizer recognizer self.running True def run(self): cap cv2.VideoCapture(self.video_path) while self.running and cap.isOpened(): ret, frame cap.read() if not ret: break self.frame_ready.emit(frame) plates self.detector.detect(frame) for box, mask, score in plates: plate_img self.detector.crop(frame, mask) chars self.recognizer.seg_and_recognize(plate_img) self.result_ready.emit(chars, score) cap.release() def stop(self): self.running Falseframe_ready信号直接连接video_label.setPixmap需要在槽函数里把 OpenCV 的 BGR 帧转成 QImage 再放到 QLabel 上。检测频率不需要每帧全跑因为摄像头帧率通常是 25fps而车牌在画面里停留时间至少几百毫秒实际工程里可以设置每 3 帧检测一次中间两帧只显示画面不推理能显著降低 CPU/GPU 占用。4.3 库表设计与记录持久化入库出库记录不能只存在内存里源码包里没有直接看到数据库文件但正常实现会带一个 SQLite 库。表结构至少包含CREATE TABLE parking_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, plate_no TEXT NOT NULL, direction TEXT CHECK(direction IN (in, out)), capture_time TEXT DEFAULT (datetime(now, localtime)), confidence REAL, image_path TEXT, status INTEGER DEFAULT 0 );status字段用于标记这条记录是否已经被计费结算。入库时插入一条directionin的记录出库时先按车牌号查最近一条directionin且status0的记录用当前时间减去入库时间得到停车时长。如果同一个车牌号 10 分钟内重复入库就要考虑是否出现了误识别这时可以弹窗让人工确认。PyQt 里操作 SQLite 直接用sqlite3模块即可但要注意所有数据库写操作尽量放在检测线程之外避免文件锁冲突。我习惯把数据库访问封装成一个DBManager类在主线程里调用检测线程只把识别结果通过信号抛出来不直接操作数据库。5. 模型推理加速与现场部署的实用技巧最后聊几个在课设和实际部署中都容易踩的细节。第一Mask R-CNN 在 CPU 上跑一张 1080p 图片大约需要 2 到 5 秒直接接到视频流里根本没法用。一个低成本优化是先把视频帧缩放到 768 宽再检测因为出入口抓拍机高度固定车牌在图像中的相对尺寸变化不大模型检测小目标的能力足够。另一个做法是只对画面中间 60% 区域做检测避开出入口两侧的干扰物能减少约 30% 的计算量。第二char_cnn.h5是在 Keras 下保存的权重加载时需要保证Keras版本和训练时一致。如果运行时报Unknown metric function一类错误多半是 HDF5 里记录了自定义层或自定义损失函数此时要改用custom_objects参数加载。如果没有自定义层那就检查tensorflow和keras的兼容版本Python 3.8 环境里keras 2.3.1 tensorflow 1.14是老组合但新版tensorflow 2.x也能直接读旧权重前提是load_model时把compileFalse传进去。char_model load_model(char_cnn.h5, compileFalse)第三夜间场景中车牌识别失败往往不是模型问题而是图像太暗导致分割阶段阈值失效。在进入 char_cnn 之前可以对车牌区域做一次 CLAHE 增强OpenCV 的createCLAHE在车牌这种小区域上效果明显比全局直方图均衡要安全。我在测试浙E6686V 那张图上做过实验直接灰度化识别准确率约 86%加上 CLAHE 后到 93%代价只是每张车牌多 5 毫秒。最后给出一个验证系统完整度的自检流程用入库.avi跑入向识别看沪KT5583.jpg这类图片能否稳定输出七位车牌再用出库.avi模拟出向过程确认同一车牌入库和出库的记录能正确配对。如果只出库不出现入库存记录先检查数据库表里的status更新逻辑再检查检测线程的result_ready信号是否被正确连接到记录插入槽函数。系统能跑通这两段视频就说明检测、识别、界面、数据库四层链路是通的。本文还有配套的精品资源点击获取
RELATED

相关推荐

打造STM32舵机库:STS3215串口帧协议与半双工总线控制

打造STM32舵机库:STS3215串口帧协议与半双工总线控制

简介:针对飞特舵机STS3215的控制库文件,面向机器人、无人机及其他自动化设备开发者,意在简化舵机驱动开发与底层通信管理。压缩包共4个文件,包含2个C源码和2个头文件:源码负责协议解析、指令发送等功能实现&#xff0c…

📅 2026/9/12 3:02:09
34mm SiC功率模块:新能源系统高效化与小型化的物理基准

34mm SiC功率模块:新能源系统高效化与小型化的物理基准

1. 项目概述:为什么34mm SiC模块正在成为新能源系统里的“心脏级”器件最近在几个光伏逆变器客户现场做技术复盘时,反复被问到一个问题:“你们说的‘基本半导体全系34mm SiC模块’,到底和我们原来用的62mm IGBT模块、甚至市面上常…

📅 2026/9/12 3:02:09
分岔系统特征提取与MPC自适应控制实战

分岔系统特征提取与MPC自适应控制实战

简介:本资源是一套面向数学、电子信息工程及计算机专业本科生的分岔动态系统预测控制参数特征分析MATLAB仿真代码集,聚焦非线性系统建模与关键参数敏感性识别问题,适用于课程设计、期末大作业及毕业设计等实践环节。压缩包共394个文件&#x…

📅 2026/9/12 3:02:09
MORE NEWS

更多资讯

📰

Material for MkDocs 自定义社交卡片:基于 default/variant 布局打造“新版本发布“公告卡片

Material for MkDocs 自定义社交卡片:基于 default/variant 布局打造"新版本发布"公告卡片 【免费下载链接】mkdocs-material Documentation that simply works 项目地址: https://gitcode.com/GitHub_Trending/mk/mkdocs-material Material for M…

📰

路面附着系数估计实战:基于EKF与UKF的Simulink实现与对比

做车辆动力学控制方向的朋友,几乎迟早都会撞上同一个问题:当前路面到底能提供多大的附着系数。ABS要靠它判断车轮会不会抱死,ESP要靠它决定要不要介入,AEB在低附着路面上能不能在目标距离内刹停,也跟它直接挂钩。这个参…

📰

阿兹海默症MRI辅助诊断系统:从CNN到Grad-CAM的深度学习实践

简介:面向高校计算机相关专业学生的深度学习应用型毕业设计项目。基于Python与Spring Boot技术栈,实现阿兹海默症早期诊断辅助系统,覆盖医学影像数据处理、模型训练与诊断结果可视化等环节,适合用于毕业设计、课程设计或作为AI医疗…

📰

VisualSVN Server+TortoiseSVN从零搭建SVN版本控制系统完整指南

从零搭建一套SVN版本控制系统:VisualSVN Server TortoiseSVN 完整实操记录我自己动手给团队搭过好几套SVN版本控制系统,也帮客户现场部署过,每次用到的组合基本都是服务端VisualSVN Server加客户端TortoiseSVN。这套方案最大的优势就是省心&…

📰

LPC1114例程详解:从GPIO到外设驱动开发实战

简介:LPC1114是NXP基于ARM Cortex-M0内核的32位微控制器,最高主频60MHz,集成ADC、UART、I2C、SPI、GPIO等丰富外设,以低功耗、高性价比被广泛用于小型控制系统、物联网终端和消费电子产品。资源以《LPC1114芯片基础教程与应用实践…

📰

AI视频生成工具横评:Higgsfield替代方案实测对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬