在智能交通和自动驾驶领域,车辆识别检测技术扮演着至关重要的角色。最近我基于最新的YOLOv10算法开发了一套高效的车辆识别系统,专门用于检测和分类四种常见车辆类型:公共汽车(bus)、小汽车(car)、摩托车(motorbike)和卡车(truck)。这个项目从数据收集到模型训练再到界面开发,前后花费了近两个月时间,期间踩过不少坑也积累了不少经验,今天就来详细分享一下这个项目的完整实现过程。
这个系统最显著的特点是能够在复杂交通场景下实现高精度的实时检测,平均检测速度达到45FPS(在RTX 3060显卡上),mAP@0.5达到0.92。系统提供了图片检测、视频检测和摄像头实时检测三种工作模式,并配备了直观的UI界面,方便非技术人员使用。下面我将从数据集构建、模型训练到系统实现,一步步拆解这个项目的技术细节。
构建高质量的数据集是目标检测项目成功的关键。考虑到实际应用场景,我特别注重数据集的多样性和真实性:
最终收集了1000张高质量图像,按照7:1:1.5的比例划分为训练集(750张)、验证集(100张)和测试集(150张)。这种划分比例确保了有足够的数据进行训练,同时也能有效评估模型性能。
使用LabelImg工具进行标注时,我制定了严格的标注规范:
标注完成后,将Pascal VOC格式转换为YOLO格式的txt文件,每个文件包含对应图像中所有目标的类别和归一化边界框信息。
为提高模型鲁棒性,我采用了多种数据增强技术:
python复制# 数据增强配置示例 (YOLOv10的数据增强参数)
augmentations = {
'hsv_h': 0.015, # 色调增强幅度
'hsv_s': 0.7, # 饱和度增强幅度
'hsv_v': 0.4, # 明度增强幅度
'translate': 0.1, # 平移增强幅度
'scale': 0.5, # 缩放增强幅度
'shear': 0.0, # 剪切增强幅度
'perspective': 0.0005, # 透视变换系数
'flipud': 0.0, # 上下翻转概率
'fliplr': 0.5, # 左右翻转概率
'mosaic': 1.0, # mosaic增强概率
'mixup': 0.1 # mixup增强概率
}
特别值得一提的是mosaic增强,它将4张训练图像拼接成1张,显著提升了模型对小目标的检测能力。在实际应用中,这种增强方式使小车辆(motorbike)的检测精度提高了约15%。
YOLOv10是Ultralytics公司2023年发布的最新版本,相比YOLOv9主要有以下改进:
Backbone优化:
Neck部分改进:
Head部分创新:
YOLOv10提供了多种规模的预训练模型,根据项目需求我选择了yolov10s作为基础模型:
训练关键参数配置:
yaml复制# 训练配置 (data/yolov10s.yaml)
lr0: 0.01 # 初始学习率
lrf: 0.01 # 最终学习率
momentum: 0.937 # SGD动量
weight_decay: 0.0005 # 权重衰减
warmup_epochs: 3.0 # 热身epochs
warmup_momentum: 0.8 # 热身动量
warmup_bias_lr: 0.1 # 热身偏置学习率
box: 7.5 # 框损失权重
cls: 0.5 # 分类损失权重
dfl: 1.5 # DFL损失权重
训练过程中,我特别关注以下指标的变化:
损失函数:
性能指标:
使用TensorBoard监控训练过程,可以清晰看到各项指标的变化趋势。在500个epoch的训练后,模型在验证集上的mAP@0.5达到了0.92,满足项目需求。
注意事项:训练初期如果出现损失震荡,可以适当降低学习率或增加warmup周期。我发现在前50个epoch使用较低学习率(0.001)有助于稳定训练。
整个系统采用模块化设计,主要分为三个部分:
code复制车辆检测系统架构
├── 检测引擎
│ ├── 模型加载模块
│ ├── 预处理模块
│ ├── 推理模块
│ └── 后处理模块
├── 接口层
│ ├── 图片处理接口
│ ├── 视频处理接口
│ └── 摄像头接口
└── UI界面
├── 主控制面板
├── 结果显示区域
└── 参数调节面板
检测线程是系统的核心,负责处理各种输入源并返回检测结果:
python复制class DetectionThread(QThread):
frame_received = pyqtSignal(np.ndarray, np.ndarray, list)
def __init__(self, model, source, conf, iou):
super().__init__()
self.model = model
self.source = source # 输入源(文件路径或摄像头ID)
self.conf = conf # 置信度阈值
self.iou = iou # IoU阈值
self.running = True # 线程控制标志
def run(self):
try:
if isinstance(self.source, int) or self.source.endswith(('.mp4', '.avi')):
# 视频/摄像头处理逻辑
cap = cv2.VideoCapture(self.source)
while self.running and cap.isOpened():
ret, frame = cap.read()
if not ret: break
# 执行检测
results = self.model(frame, conf=self.conf, iou=self.iou)
annotated_frame = results[0].plot()
# 提取检测结果
detections = []
for box in results[0].boxes:
class_id = int(box.cls)
confidence = float(box.conf)
x, y, w, h = box.xywh[0].tolist()
detections.append((class_id, confidence, x, y))
# 发送结果信号
self.frame_received.emit(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB),
cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB),
detections
)
time.sleep(0.03) # 控制帧率
cap.release()
else:
# 图片处理逻辑
frame = cv2.imread(self.source)
results = self.model(frame, conf=self.conf, iou=self.iou)
# ...(类似处理逻辑)
except Exception as e:
print(f"Detection error: {e}")
使用PyQt5实现了一个功能完整的用户界面,主要特性包括:
python复制class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("车辆检测系统 v1.0")
self.resize(1200, 800)
# 初始化模型
self.model = YOLOv10('yolov10s.pt')
# 创建UI组件
self.create_controls()
self.create_display()
self.create_status_bar()
# 连接信号槽
self.image_btn.clicked.connect(self.load_image)
self.video_btn.clicked.connect(self.load_video)
self.camera_btn.clicked.connect(self.start_camera)
self.stop_btn.clicked.connect(self.stop_detection)
def create_controls(self):
"""创建控制面板"""
control_panel = QWidget()
layout = QVBoxLayout()
# 模型选择
self.model_combo = QComboBox()
self.model_combo.addItems(['yolov10n', 'yolov10s', 'yolov10m'])
# 参数调节
self.conf_slider = QSlider(Qt.Horizontal)
self.iou_slider = QSlider(Qt.Horizontal)
# 功能按钮
self.image_btn = QPushButton("图片检测")
self.video_btn = QPushButton("视频检测")
self.camera_btn = QPushButton("摄像头检测")
self.stop_btn = QPushButton("停止检测")
# 添加到布局
layout.addWidget(QLabel("模型选择:"))
layout.addWidget(self.model_combo)
layout.addSpacing(20)
# ...(其他UI组件添加)
control_panel.setLayout(layout)
return control_panel
在实际部署中,我采用了多种优化手段提升系统性能:
半精度推理:使用FP16精度,速度提升30%且精度损失小于1%
python复制model = YOLOv10('yolov10s.pt').half() # 半精度模型
TensorRT加速:将模型转换为TensorRT引擎,速度提升2-3倍
bash复制python export.py --weights yolov10s.pt --include engine --device 0
批处理优化:对视频检测采用批处理模式,充分利用GPU并行能力
IO优化:使用多线程处理图像加载和预处理,减少流水线阻塞
为了使系统能在不同环境中运行,我准备了多种部署方案:
本地部署:
Docker部署:
dockerfile复制FROM nvidia/cuda:11.8.0-base
RUN apt-get update && apt-get install -y python3-pip
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /app
WORKDIR /app
CMD ["python", "main.py"]
Web API服务:
python复制@app.post("/detect")
async def detect(file: UploadFile = File(...)):
image = cv2.imdecode(np.frombuffer(await file.read(), np.uint8), cv2.IMREAD_COLOR)
results = model(image)
return {"results": results[0].tolist()}
在150张测试图像上,系统表现出色:
| 类别 | 精确率 | 召回率 | mAP@0.5 |
|---|---|---|---|
| 公共汽车 | 0.94 | 0.91 | 0.93 |
| 小汽车 | 0.95 | 0.93 | 0.94 |
| 摩托车 | 0.88 | 0.85 | 0.87 |
| 卡车 | 0.92 | 0.89 | 0.91 |
| 平均 | 0.92 | 0.90 | 0.92 |
摩托车检测精度相对较低,主要原因是其尺寸较小且形状多变。后续可以通过增加小目标样本和针对性数据增强来改善。
在实际测试中遇到几个典型问题及解决方法:
夜间检测效果差:
cv2.createCLAHE() 进行自适应直方图均衡化密集场景漏检:
anchors: [3,6, 5,9, 8,16] (更适合小目标)GPU内存不足:
python复制def auto_resize(image, max_size=1280):
h, w = image.shape[:2]
scale = min(max_size/h, max_size/w)
return cv2.resize(image, (int(w*scale), int(h*scale)))
这个车辆检测系统已经具备了较好的实用价值,但仍有改进空间:
一个特别有前景的扩展方向是将系统与交通信号控制相结合,实现智能化的交通流量调节。我们已经开始与本地交通管理部门合作,在几个路口进行试点测试。