1. 项目概述
这个基于YOLOv11的目标检测系统是我最近完成的一个实用项目,主要解决办公场所和公共场所的行为规范管理问题。系统能够实时检测三种常见目标:吸烟行为(smoke)、水杯(drink)和手机(phone),适用于安全生产监控、办公环境管理等场景。
作为一名长期从事计算机视觉开发的工程师,我发现这类特定场景下的目标检测需求在实际应用中非常普遍。与通用目标检测不同,这类专用系统需要在特定目标上达到更高的精度和实时性。这也是我选择YOLOv11作为基础算法的原因——它在保持YOLO系列实时性的同时,通过结构优化提升了小目标检测能力。
2. 技术选型与架构设计
2.1 为什么选择YOLOv11
YOLOv11是Ultralytics团队在2023年推出的最新版本,相比前代有几个显著优势:
- 骨干网络优化:采用了更高效的CSPNet结构,在保持轻量化的同时提升了特征提取能力
- 注意力机制:引入了SimAM无参注意力模块,特别适合处理小目标(如香烟、手机)
- 训练策略改进:使用了Mosaic-9数据增强和更科学的损失函数设计
在实际测试中,YOLOv11s(small版本)在我们的数据集上达到了86.5%的mAP,同时保持45FPS的推理速度(RTX 3060显卡),完全满足实时监控需求。
2.2 系统架构设计
整个系统采用模块化设计,主要分为三个层次:
- 算法层:基于YOLOv11的检测模型,负责目标识别和定位
- 服务层:处理视频流、结果可视化和数据存储
- 应用层:用户交互界面和系统管理功能
code复制┌───────────────────────┐
│ 应用层 │
│ ┌─────────────────┐ │
│ │ PyQt5 UI界面 │ │
│ └─────────────────┘ │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ 服务层 │
│ ┌─────────────────┐ │
│ │ 视频流处理 │ │
│ ├─────────────────┤ │
│ │ 结果可视化 │ │
│ ├─────────────────┤ │
│ │ 数据存储 │ │
│ └─────────────────┘ │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ 算法层 │
│ ┌─────────────────┐ │
│ │ YOLOv11模型 │ │
│ └─────────────────┘ │
└───────────────────────┘
这种分层设计使得系统各模块耦合度低,便于后期维护和功能扩展。例如,如果需要增加新的检测类别,只需重新训练算法层的模型,其他层几乎不需要改动。
3. 数据集构建与处理
3.1 数据集概况
我们收集了3,507张标注图像,分为3,157张训练集和350张验证集。数据分布如下:
| 类别 | 训练集数量 | 验证集数量 | 合计 |
|---|---|---|---|
| smoke | 1,205 | 134 | 1,339 |
| drink | 987 | 110 | 1,097 |
| phone | 965 | 106 | 1,071 |
| 总计 | 3,157 | 350 | 3,507 |
数据采集主要来自三个场景:
- 办公室监控视频截图
- 公共场所拍摄照片
- 网络公开数据集中的相关图片
3.2 数据标注与增强
所有图像都使用LabelImg工具进行标注,采用YOLO格式保存。为提高模型鲁棒性,我们实施了以下数据增强策略:
- Mosaic-9增强:将9张图像拼接训练,提升小目标检测能力
- 随机色彩抖动:调整亮度、对比度和饱和度,模拟不同光照条件
- 随机旋转:±15度范围内旋转,增强角度不变性
- MixUp:两幅图像线性混合,增加数据多样性
标注文件示例:
code复制0 0.543201 0.491211 0.120312 0.210101 # smoke
1 0.321045 0.689212 0.080123 0.150222 # drink
2 0.712345 0.512345 0.050123 0.090321 # phone
3.3 数据集配置文件
数据集采用标准YOLO格式组织,data.yaml配置如下:
yaml复制train: datasets/train/images
val: datasets/valid/images
test:
nc: 3
names: ['smoke', 'drink', 'phone']
4. 模型训练与优化
4.1 训练环境配置
我们使用Python 3.9和PyTorch 1.12搭建训练环境,具体配置步骤如下:
- 创建conda虚拟环境:
bash复制conda create -n yolov11 python=3.9
conda activate yolov11
- 安装PyTorch和依赖库:
bash复制pip install torch torchvision torchaudio
pip install ultralytics opencv-python pyqt5
- 克隆YOLOv11仓库:
bash复制git clone https://github.com/ultralytics/yolov11
cd yolov11
pip install -r requirements.txt
4.2 训练参数设置
我们使用YOLOv11s预训练模型进行迁移学习,主要训练参数如下:
python复制from ultralytics import YOLO
model = YOLO('yolov11s.pt') # 加载预训练模型
results = model.train(
data='data.yaml',
epochs=100,
batch=8,
imgsz=640,
device='0', # 使用GPU 0
workers=4,
project='runs',
name='exp',
patience=10, # 早停轮数
lr0=0.01, # 初始学习率
lrf=0.1, # 最终学习率
momentum=0.9,
weight_decay=0.0005,
warmup_epochs=3,
warmup_momentum=0.8
)
关键参数说明:
batch=8:根据GPU显存调整,RTX 3060(12GB)可设置8-16imgsz=640:输入图像尺寸,平衡精度和速度patience=10:验证指标10轮无提升则提前停止warmup_epochs=3:前3轮渐进式增加学习率,避免初期震荡
4.3 训练过程监控
训练过程中主要监控以下指标:
-
损失函数变化:
- box_loss:边界框回归损失
- cls_loss:分类损失
- dfl_loss:分布焦点损失
-
性能指标:
- mAP@0.5:IoU阈值为0.5时的平均精度
- mAP@0.5:0.95:IoU阈值从0.5到0.95的平均精度
- precision:精确率
- recall:召回率
典型训练曲线如下:

4.4 模型评估与优化
训练完成后,在验证集上的评估结果如下:
| 指标 | smoke | drink | phone | 平均 |
|---|---|---|---|---|
| 精确率 | 0.892 | 0.876 | 0.901 | 0.890 |
| 召回率 | 0.845 | 0.831 | 0.862 | 0.846 |
| mAP@0.5 | 0.881 | 0.865 | 0.893 | 0.880 |
| mAP@0.5:0.95 | 0.645 | 0.632 | 0.668 | 0.648 |
针对误检和漏检问题,我们采取了以下优化措施:
- 困难样本挖掘:收集模型预测错误的样本,加入训练集重新训练
- 类别平衡采样:对样本较少的类别(如drink)进行过采样
- 测试时增强(TTA):推理时使用多尺度变换提升小目标检测能力
优化后模型性能提升约3-5%,特别是对小目标(如香烟)的检测效果改善明显。
5. 系统实现与核心代码
5.1 多线程检测框架
为实现流畅的实时检测,我们采用多线程架构,将检测任务与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):
cap = cv2.VideoCapture(self.source) if isinstance(self.source, int) else None
try:
while self.running:
if cap: # 视频或摄像头
ret, frame = cap.read()
if not ret: break
else: # 图片
frame = cv2.imread(self.source)
if frame is None: break
# 执行检测
results = self.model(frame, conf=self.conf, iou=self.iou)
annotated = results[0].plot() # 绘制检测结果
# 提取检测信息
detections = []
for box in results[0].boxes:
cls = int(box.cls)
conf = float(box.conf)
x, y = box.xywh[0][:2].tolist()
detections.append((self.model.names[cls], conf, x, y))
# 发送结果到主线程
self.frame_received.emit(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB),
cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB),
detections
)
if not cap: break # 图片只处理一次
time.sleep(0.03) # 控制帧率
finally:
if cap: cap.release()
self.running = False
5.2 用户界面设计
使用PyQt5实现科幻风格的交互界面,主要特点包括:
- 双画面显示:左侧原始画面,右侧检测结果
- 实时数据表格:显示检测目标的类别、置信度和位置
- 参数控制面板:可调整置信度和IoU阈值
- 状态监控区:显示系统状态和性能指标
核心UI代码结构:
python复制class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# 初始化模型
self.model = YOLO('yolov11s.pt')
# 创建UI组件
self.create_controls()
self.create_display()
self.create_status_bar()
# 连接信号槽
self.connect_slots()
def create_controls(self):
"""创建控制面板"""
self.conf_slider = QSlider(Qt.Horizontal)
self.iou_slider = QSlider(Qt.Horizontal)
self.model_combo = QComboBox()
self.start_btn = QPushButton("开始检测")
self.stop_btn = QPushButton("停止")
# 样式设置
self.set_style_sheet()
def create_display(self):
"""创建显示区域"""
self.original_view = QLabel()
self.result_view = QLabel()
self.result_table = QTableWidget()
# 布局管理
splitter = QSplitter(Qt.Horizontal)
splitter.addWidget(self.original_view)
splitter.addWidget(self.result_view)
def set_style_sheet(self):
"""设置科幻风格样式表"""
self.setStyleSheet("""
QMainWindow {
background-color: #0a0a1a;
color: #00ffff;
}
QPushButton {
border: 1px solid #00ffff;
border-radius: 5px;
padding: 5px;
background: rgba(0, 100, 100, 0.3);
}
QPushButton:hover {
background: rgba(0, 150, 150, 0.5);
box-shadow: 0 0 10px #00ffff;
}
""")
5.3 检测结果处理
检测结果的处理和显示逻辑:
python复制def handle_detection_result(self, original, result, detections):
"""处理检测结果并更新UI"""
# 显示图像
self.display_image(self.original_view, original)
self.display_image(self.result_view, result)
# 更新表格
self.result_table.setRowCount(0)
for i, (cls, conf, x, y) in enumerate(detections):
self.result_table.insertRow(i)
self.result_table.setItem(i, 0, QTableWidgetItem(cls))
self.result_table.setItem(i, 1, QTableWidgetItem(f"{conf:.2f}"))
self.result_table.setItem(i, 2, QTableWidgetItem(f"{x:.1f}"))
self.result_table.setItem(i, 3, QTableWidgetItem(f"{y:.1f}"))
# 保存结果(如果启用)
if self.save_flag:
self.save_result(original, result, detections)
# 更新状态
fps = 1.0 / (time.time() - self.last_time)
self.status_bar.showMessage(
f"检测中 | FPS: {fps:.1f} | 检测目标: {len(detections)}个"
)
self.last_time = time.time()
6. 系统部署与性能优化
6.1 环境配置指南
对于实际部署,我们推荐以下两种方案:
开发环境配置:
bash复制# 创建conda环境
conda create -n yolov11 python=3.9
conda activate yolov11
# 安装PyTorch(根据CUDA版本选择)
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html
# 安装其他依赖
pip install ultralytics opencv-python pyqt5 numpy pandas
生产环境Docker部署:
dockerfile复制FROM nvidia/cuda:11.3.1-base
# 安装系统依赖
RUN apt-get update && apt-get install -y \
python3.9 \
python3-pip \
libgl1
# 设置工作目录
WORKDIR /app
# 复制代码和模型
COPY . .
# 安装Python依赖
RUN pip install -r requirements.txt
# 启动命令
CMD ["python", "main.py"]
6.2 性能优化技巧
在实际部署中,我们总结了以下优化经验:
-
模型量化:使用FP16或INT8量化减小模型大小,提升推理速度
python复制model.export(format='onnx', half=True) # FP16量化 -
TensorRT加速:将模型转换为TensorRT引擎
bash复制
trtexec --onnx=yolov11s.onnx --saveEngine=yolov11s.trt -
多流处理:对于多路视频输入,使用多进程并行处理
python复制from multiprocessing import Process def process_stream(rtsp_url): cap = cv2.VideoCapture(rtsp_url) while True: ret, frame = cap.read() # 检测处理... if __name__ == '__main__': streams = ['rtsp://cam1', 'rtsp://cam2'] for url in streams: p = Process(target=process_stream, args=(url,)) p.start() -
视频流优化:使用FFmpeg硬件加速解码
python复制cap = cv2.VideoCapture() cap.open('rtsp://...', cv2.CAP_FFMPEG)
6.3 不同硬件平台性能对比
我们在多种硬件平台上测试了系统性能:
| 硬件平台 | 分辨率 | FPS | 功耗(W) | 适用场景 |
|---|---|---|---|---|
| NVIDIA Jetson AGX Orin | 1920x1080 | 32 | 30 | 边缘计算盒子 |
| RTX 3060 | 1920x1080 | 45 | 170 | 工作站/服务器 |
| Intel i7-12700H | 1280x720 | 12 | 45 | 普通PC |
| Raspberry Pi 5 | 640x480 | 2.5 | 5 | 轻量级测试 |
对于实时监控场景,建议至少使用RTX 3060级别显卡或Jetson AGX Orin边缘计算设备。
7. 常见问题与解决方案
7.1 模型训练问题
问题1:训练早期损失震荡大
- 原因:学习率设置过高或数据分布不均匀
- 解决:
python复制model.train( lr0=0.01, # 降低初始学习率 warmup_epochs=5, # 增加热身轮数 warmup_momentum=0.8 # 降低初始动量 )
问题2:验证集mAP低于训练集
- 原因:模型过拟合
- 解决:
python复制model.train( dropout=0.2, # 添加Dropout层 weight_decay=0.0005, # 增加权重衰减 patience=15 # 早停防止过拟合 )
7.2 部署运行时问题
问题1:检测结果闪烁不稳定
- 原因:视频帧间目标匹配不连续
- 解决:实现简单的跟踪算法
python复制from collections import defaultdict class Tracker: def __init__(self): self.tracks = defaultdict(dict) self.next_id = 0 def update(self, detections): # 简单IOU匹配 for det in detections: matched = False for tid, track in self.tracks.items(): if self.iou(det['bbox'], track['bbox']) > 0.5: det['id'] = tid matched = True break if not matched: det['id'] = self.next_id self.next_id += 1 return detections
问题2:内存泄漏
- 原因:PyQt5和OpenCV资源未正确释放
- 解决:确保正确释放资源
python复制def closeEvent(self, event): if self.detection_thread: self.detection_thread.stop() self.detection_thread.wait() if self.video_writer: self.video_writer.release() event.accept()
7.3 性能优化问题
问题1:GPU利用率低
- 原因:数据预处理成为瓶颈
- 解决:使用DALI加速数据加载
python复制from nvidia.dali import pipeline_def import nvidia.dali.fn as fn @pipeline_def def video_pipeline(): videos = fn.readers.video(device="gpu", filenames=["video.mp4"]) return fn.resize(videos, resize_x=640, resize_y=640)
问题2:多路视频处理卡顿
- 原因:Python GIL限制
- 解决:使用多进程代替多线程
python复制from multiprocessing import Process, Queue def worker(input_q, output_q): model = YOLO('yolov11s.pt') while True: frame = input_q.get() results = model(frame) output_q.put(results) # 主进程 input_queues = [Queue() for _ in range(4)] output_queue = Queue() workers = [Process(target=worker, args=(iq, output_queue)) for iq in input_queues]
8. 项目扩展方向
8.1 功能扩展建议
-
行为分析:在目标检测基础上增加行为识别,如"吸烟+打电话"复合行为
python复制def analyze_behavior(detections): smoke = any(d[0] == 'smoke' for d in detections) phone = any(d[0] == 'phone' for d in detections) if smoke and phone: return "smoking_while_calling" elif smoke: return "smoking" elif phone: return "using_phone" return "normal" -
人脸模糊:对检测到的人员面部进行隐私保护
python复制def blur_faces(frame, detections): for d in detections: if d[0] == 'person': x, y, w, h = d[2:] face = frame[y:y+h, x:x+w] face = cv2.GaussianBlur(face, (23, 23), 30) frame[y:y+h, x:x+w] = face return frame -
云端管理:将检测结果上传至云端平台
python复制import requests def upload_to_cloud(data): url = "https://api.example.com/detections" headers = {"Authorization": "Bearer YOUR_TOKEN"} response = requests.post(url, json=data, headers=headers) return response.status_code == 200
8.2 模型优化方向
-
知识蒸馏:使用大模型指导小模型训练
python复制teacher = YOLO('yolov11x.pt') # 大模型 student = YOLO('yolov11s.pt') # 小模型 # 蒸馏训练 for images, targets in dataloader: with torch.no_grad(): t_preds = teacher(images) s_preds = student(images) loss = kd_loss(s_preds, t_preds) + detection_loss(s_preds, targets) loss.backward() -
自动超参优化:使用Optuna自动搜索最佳参数
python复制import optuna def objective(trial): lr = trial.suggest_float('lr', 1e-5, 1e-3, log=True) batch = trial.suggest_categorical('batch', [8, 16, 32]) model = YOLO('yolov11s.pt') results = model.train(data='data.yaml', epochs=50, lr0=lr, batch=batch) return results.results_dict['metrics/mAP50-95(B)'] -
模型剪枝:移除冗余参数加速推理
python复制from torch.nn.utils import prune model = YOLO('yolov11s.pt') parameters_to_prune = [(module, 'weight') for module in model.model.modules() if isinstance(module, nn.Conv2d)] prune.global_unstructured(parameters_to_prune, pruning_method=prune.L1Unstructured, amount=0.3)
9. 实际应用案例
9.1 办公场所管理
在某科技公司部署后,系统实现了以下效果:
- 吸烟行为识别准确率:92.3%
- 平均响应时间:<500ms
- 每日违规行为预警:15-20次
典型工作流程:
- 系统检测到吸烟行为
- 自动截图并记录时间地点
- 发送邮件通知安全管理员
- 生成月度违规统计报表
9.2 生产安全管理
在化工厂的应用场景:
- 禁烟区域实时监控
- 危险区域手机使用检测
- 员工饮水区域合规监测
集成方案:
mermaid复制graph LR
A[摄像头] --> B[检测系统]
B --> C{违规判断}
C -->|是| D[声光报警]
C -->|否| E[正常记录]
D --> F[管理中心]
E --> F
9.3 教育机构应用
在学校机房部署实现了:
- 手机使用检测准确率:89.7%
- 水杯放置区域监控
- 与考勤系统联动分析行为数据
数据分析维度:
python复制def analyze_behavior_data():
return {
'time_distribution': {
'phone': {'08:00-10:00': 15, '10:00-12:00': 23},
'drink': {'08:00-10:00': 8, '10:00-12:00': 12}
},
'location_heatmap': {
'phone': [(x1,y1), (x2,y2)],
'drink': [(x3,y3), (x4,y4)]
}
}
10. 项目总结与经验分享
在完成这个项目的过程中,我积累了一些值得分享的经验:
-
数据质量决定上限:初期由于数据标注不统一(特别是吸烟行为的不同姿态),模型表现不稳定。通过增加标注样本和统一标注标准后,mAP提升了约12%。
-
模型不是越大越好:尝试YOLOv11x大模型后发现推理速度无法满足实时要求,最终选择YOLOv11s并在特定层添加注意力模块,取得了速度和精度的平衡。
-
UI响应是关键:最初版本由于检测和UI在同一线程,界面经常卡顿。改为多线程架构后,用户体验显著改善。
-
边缘部署的挑战:在Jetson设备上部署时遇到TensorRT兼容性问题,最终通过自定义插件解决。建议边缘部署时预留足够的调试时间。
对于想要尝试类似项目的开发者,我的建议是:
- 先从小的POC(概念验证)开始,验证核心功能可行性
- 重视数据收集和清洗环节,这往往比模型调参更有效
- 生产环境部署要考虑异常处理和日志监控
- 持续关注YOLO系列的最新进展,及时应用新特性
这个项目的完整代码和预训练模型我已经开源,希望能对计算机视觉和智能监控领域的开发者有所帮助。在实际应用中,可以根据具体需求调整检测类别和报警规则,打造更适合自己场景的行为管理系统。
