去年参与某智慧园区项目时,客户要求对进出车辆实现自动化分类统计。传统方案要么依赖高精度摄像头配合专用算法芯片,要么需要人工抽查录像,成本与效率难以兼顾。这套基于YOLO系列模型的车型识别系统,正是我在解决该需求时的技术沉淀。
系统核心采用模块化设计:底层是YOLOv5到v12的模型矩阵,中间层用PyQt5构建带用户系统的可视化界面,顶层整合了多模态检测与数据导出功能。特别在模型选型上,经过实测对比发现YOLOv12n在640像素输入下能达到40.6%的mAP,而YOLOv11n的CPU推理速度仅56.1毫秒,这种精度与速度的平衡在实际部署中至关重要。
系统采用典型的三层架构:
这种解耦设计使得模型升级不影响界面交互,比如新增YOLOv13只需在算法层替换模型文件。实际部署时,我们将检测服务封装成gRPC接口,实现前后端完全分离。
PyQt5 vs Tkinter:虽然Tkinter更轻量,但PyQt5的QSS样式表和信号槽机制更适合复杂界面开发。实测在渲染带标注的1080p视频时,PyQt5的QPixmap比Tkinter的PhotoImage快3倍。
SQLite的优化技巧:通过WAL模式(wal_mode=1)提升并发写入性能,用户数据表添加索引后查询速度提升15倍:
sql复制CREATE INDEX idx_username ON users(username);
模型部署方案:采用ONNX Runtime替代原生PyTorch推理,在树莓派4B上使YOLOv8n的推理速度从2.1FPS提升到4.7FPS。
项目使用的19,000张车辆图片需满足:
数据增强策略特别增加了:
python复制transform = A.Compose([
A.RandomRain(drop_length=10, blur_value=3, p=0.3), # 模拟雨天
A.RandomShadow(num_shadows_low=1, num_shadows_high=3, p=0.5) # 增加阴影干扰
])
在YOLOv12n训练中发现:
yaml复制lr0: 0.001
lrf: 0.01
warmup_epochs: 5
box: 0.05 # 调整box loss权重
在NVIDIA Jetson Xavier NX上的测试结果:
| 模型 | 推理时延(ms) | 显存占用(MB) | 准确率(%) |
|---|---|---|---|
| YOLOv5nu | 68 | 1200 | 72.1 |
| YOLOv8n | 53 | 1450 | 75.3 |
| YOLOv11n | 41 | 1100 | 77.8 |
| YOLOv12n | 46 | 1300 | 79.4 |
注:测试环境为640x640输入,TensorRT加速
采用生产者-消费者模式解决界面卡顿:
python复制class DetectorThread(QThread):
result_signal = pyqtSignal(np.ndarray)
def __init__(self, model):
super().__init__()
self.model = model
self.queue = Queue(maxsize=3)
def run(self):
while True:
img = self.queue.get()
results = self.model(img)
self.result_signal.emit(results.plot())
Excel导出模块使用openpyxl的流式写入:
python复制def save_to_excel(detections, path):
wb = Workbook(write_only=True)
ws = wb.create_sheet()
for det in detections:
ws.append([
det['frame_id'],
det['class_name'],
f"{det['confidence']:.2f}",
*det['bbox']
])
wb.save(path)
相比pandas.to_excel,内存占用降低80%。
症状:切换YOLOv8到v12时界面冻结3秒
根因:PyQt5在主线程加载模型
解决方案:
python复制def load_model_async(model_path):
thread = ModelLoaderThread(model_path)
thread.finished.connect(on_model_loaded)
thread.start()
使用OpenCV的VideoCapture时,未释放cap对象会导致内存持续增长。正确做法:
python复制def video_detect(path):
cap = cv2.VideoCapture(path)
try:
while cap.isOpened():
ret, frame = cap.read()
if not ret: break
yield process_frame(frame)
finally:
cap.release() # 确保资源释放
发现cv2.resize占用了30%推理时间,改用GPU加速:
python复制frame = cv2.cuda_GpuMat(frame)
resized = cv2.cuda.resize(frame, (640, 640))
使用TensorRT的FP16量化:
bash复制trtexec --onnx=yolov12n.onnx --fp16 --saveEngine=yolov12n_fp16.engine
量化后模型体积减小50%,推理速度提升35%。
通过ROI区域检测实现:
python复制def count_vehicles(results, roi_polygon):
counts = defaultdict(int)
for det in results:
if is_in_polygon(det.xyxy[0], roi_polygon):
counts[det.cls] += 1
return counts
结合目标追踪算法:
python复制tracker = BYTETracker()
for frame in video:
detections = model(frame)
tracks = tracker.update(detections)
for track in tracks:
if track.stationary_time > 300: # 静止超过5分钟
alert_illegal_parking(track)
这套系统在多个园区落地后,车辆识别准确率从人工巡查的85%提升到98%,人力成本降低70%。特别在夜间低照度环境下,通过增加红外图像训练数据,仍能保持92%以上的识别率。对于希望快速搭建车型识别系统的开发者,建议从YOLOv11n入手,其在精度和速度上取得了较好的平衡。