news 2026/9/24 18:16:25

基于YOLOv8的智慧工厂危险区域闯入识别系统:从训练到部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于YOLOv8的智慧工厂危险区域闯入识别系统:从训练到部署

简介:这份资源面向计算机、人工智能、自动化等专业的在校学生与教师,提供一套可直接运行的智慧工厂危险区域闯入识别方案,适合作为毕业设计、课程设计或大作业的完整参考。项目以YOLOv8目标检测为核心,配套可视化界面,能够对工厂危险区域的人员闯入行为进行实时识别与预警,兼顾算法训练与交互展示。压缩包共8个文件,约15.91MB,包含3个Python脚本、3个模型权重文件与2个说明文本,分别对应模型训练、视频检测、可视化页面设计以及预训练权重与使用说明,结构清晰、便于快速部署。资源内还提供核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果与标签分布图等完整实验产物,方便直接用于答辩展示与结果分析。目前已有28人学习下载,代码均经测试运行成功,拿来即可上手,也可在此基础上修改扩展,实现更多检测功能。

1. 从一次产线误报说起:危险区域闯入识别到底难在哪

去年帮一家做汽车零部件冲压的客户做安全改造,他们最头疼的不是摄像头不够,而是误报太多。冲压机旁边划了黄色警戒线,工人偶尔伸手取件,传统方案用红外对射或者区域像素变化检测,结果一只飞鸟、一束叉车灯光、甚至蒸汽都能触发停机,一天停十几次,产线班长直接把报警器电源拔了。这就是危险区域闯入识别最真实的痛点:不是检测不到人,而是分不清「人」和「像人的东西」,更分不清「路过」和「闯入」。

基于 YOLOv8 的智慧工厂危险区域闯入识别系统,核心思路是把目标检测和区域逻辑判断拆开:YOLOv8 负责在每一帧里稳定找出 person 这个类,区域判断负责回答「这个人的脚底点有没有落在危险多边形内」。这样做的好处是模型只学「人长什么样」,区域规则可以随时改,换车间、换工位不用重新训练。这套方案适合做毕设或课程设计的同学,也适合工厂里想快速验证视觉安全方案的工程师,因为源码、数据集、可视化界面和部署教程都打包好了,简单部署即可运行,不用从零搭环境。

我见过太多人一上来就调 YOLOv8 的 head 或者换 backbone,结果连标注格式都没对齐,训练 loss 都不降。先把「检测 + 区域判断」这条链路跑通,再谈改进,才是正经落地路径。下面按我实际部署的顺序,从环境、数据、训练、区域逻辑到可视化界面,一步步拆开讲。

2. 环境配置与 YOLOv8 安装:CPU 版本也能先跑通

2.1 为什么建议先用 CPU 版本验证链路

很多同学拿到源码第一反应是找 GPU,但如果你手头只有一台办公笔记本,或者实验室服务器暂时排不上,用 CPU 版本先把推理和区域判断跑通完全可行。YOLOv8n 在 CPU 上单帧推理大约 80 到 150 毫秒,对于危险区域闯入这种不需要 60 帧实时性的场景,5 到 10 FPS 足够触发报警。等链路验证没问题,再换 GPU 训练自己的数据集,效率会高很多。

Ubuntu 20.04 和 CentOS 7 都能装,但 CentOS 7 默认 Python 版本太低,建议用 conda 建独立环境。Windows 上跑可视化界面也没问题,只是 OpenCV 的 GUI 依赖需要额外注意。我一般会先建一个干净的虚拟环境,避免和系统里的包打架。

# 创建 Python 3.9 虚拟环境,YOLOv8 对 3.8-3.10 支持最好 conda create -n yolov8_factory python=3.9 -y conda activate yolov8_factory # 安装 PyTorch CPU 版本,注意去官网复制对应命令,这里以 pip 为例 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics 和可视化界面依赖 pip install ultralytics opencv-python pillow pyyaml tqdm

这段命令的逻辑是:先隔离环境,再装 PyTorch 作为 YOLOv8 的推理后端,最后装 ultralytics 这个官方库。参数上唯一要注意的是 PyTorch 版本,如果你后面要换 GPU,把--index-url换成 CUDA 对应的地址即可。装完后用yolo checks验证,能看到环境信息就说明基础链路通了。

2.2 验证 YOLOv8 安装是否成功的最小命令

不要急着跑训练,先用官方预训练权重做一次推理,确认模型能加载、能出框。这一步能排除 80% 的环境问题。

# 下载 yolov8n.pt 并在一张测试图上推理 yolo predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg' save=True

如果这条命令能跑通并在runs/detect/predict下生成带框的图片,说明 YOLOv8 安装没问题。常见翻车点是网络下载权重失败,可以手动下载yolov8n.pt放到当前目录,把model=改成./yolov8n.pt。另一个坑是 OpenCV 版本冲突,如果报cv2.imshow相关错误,重装opencv-python-headless换成opencv-python即可。

提示:CPU 版本推理时把imgsz设成 640 就够了,设太大只会拖慢速度,对危险区域判断精度提升有限。

3. 数据集处理:从 Labelme 标注到 YOLOv8 格式的完整转换

3.1 危险区域闯入数据集应该标什么

这个系统的数据集不需要标「闯入」这个行为,只需要标person一个类。因为闯入是区域逻辑判断的结果,不是视觉特征。我见过有人把「人」和「闯入的人」分成两类标,结果模型根本学不会,因为同一个人的姿态在不同帧里差异太大。正确做法是:所有出现人的帧都标person,框要贴紧人体,包括被设备部分遮挡的情况。

数据集来源可以是工厂实地拍摄,也可以用公开行人数据集补充。关键是场景要覆盖你的目标车间:光照变化、人员穿工服、戴安全帽、叉车经过遮挡等。一般 2000 到 5000 张图就能出一个可用的模型,太少容易过拟合,太多标注成本高。Labelme 标注后会生成 JSON 文件,每个 JSON 对应一张图,里面记录了多边形或矩形框的坐标。

3.2 Labelme JSON 转 YOLO txt 的脚本与四个边界坑

YOLOv8 需要的是每张图一个.txt,每行class_id x_center y_center width height,全部归一化到 0 到 1。下面这个脚本我用了很多次,直接改路径就能跑。

import json import os from pathlib import Path # 输入 Labelme JSON 文件夹,输出 YOLO 标签文件夹 json_dir = Path("labelme_jsons") out_dir = Path("yolo_labels") out_dir.mkdir(exist_ok=True) # 类别映射,这里只有 person 一类 class_map = {"person": 0} for json_file in json_dir.glob("*.json"): with open(json_file, "r", encoding="utf-8") as f: data = json.load(f) img_w = data["imageWidth"] img_h = data["imageHeight"] lines = [] for shape in data["shapes"]: label = shape["label"] if label not in class_map: continue points = shape["points"] # 取多边形或矩形的外接矩形 xs = [p[0] for p in points] ys = [p[1] for p in points] x_min, x_max = min(xs), max(xs) y_min, y_max = min(ys), max(ys) # 边界裁剪,防止标注超出图像范围 x_min = max(0, min(x_min, img_w - 1)) x_max = max(0, min(x_max, img_w - 1)) y_min = max(0, min(y_min, img_h - 1)) y_max = max(0, min(y_max, img_h - 1)) # 归一化中心点和宽高 x_center = (x_min + x_max) / 2.0 / img_w y_center = (y_min + y_max) / 2.0 / img_h w = (x_max - x_min) / img_w h = (y_max - y_min) / img_h # 过滤掉宽高为 0 的无效框 if w <= 0 or h <= 0: continue lines.append(f"{class_map[label]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") # 即使没有目标也要生成空文件,否则训练时会报找不到标签 with open(out_dir / (json_file.stem + ".txt"), "w") as f: f.write("\n".join(lines))

逻辑说明:脚本遍历每个 JSON,读取图像宽高,把每个person形状转成外接矩形,再归一化。四个边界坑分别是:第一,标注点可能超出图像边界,不裁剪会导致归一化值大于 1,训练时报错;第二,宽或高为 0 的框要过滤,否则 YOLOv8 会报invalid labels;第三,没有目标的图也要生成空 txt,否则数据集校验会失败;第四,类别名必须和data.yaml里的names顺序一致,这里person对应 0。

3.3 data.yaml 的写法与训练集验证集划分

转换完标签后,按 8:1:1 划分训练、验证、测试集,目录结构建议如下:

dataset/ images/ train/ val/ test/ labels/ train/ val/ test/

然后写data.yaml

path: ./dataset train: images/train val: images/val test: images/test nc: 1 names: ["person"]

nc是类别数,这里只有 person 所以是 1。names的顺序必须和转换脚本里的class_map一致。如果后面要加安全帽、反光衣等类别,改这里和脚本里的映射即可,但危险区域闯入本身只需要 person。

4. 训练自己的数据集:参数怎么设、曲线怎么看

4.1 YOLOv8 训练命令与关键参数解释

环境、数据都准备好后,训练命令其实很短,但参数设不对会浪费很多时间。

yolo detect train \ data=dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs_factory \ name=exp1

逐项说明:model=yolov8n.pt表示从预训练权重开始微调,比自己从头训快很多;epochs=100对 2000 到 5000 张图足够,如果 loss 还在降可以加到 150;imgsz=640是输入分辨率,工厂场景里人占画面比例不大,640 够用,想提升小目标可以试 960 但显存要够;batch=16在 8G 显存上比较稳,CPU 训练就设 4 或 8;lr0=0.01是初始学习率,微调时不要设太大,否则预训练权重会被冲掉;patience=20表示 20 轮验证指标不提升就早停,省时间。

训练开始后,终端会打印每轮的 box_loss、cls_loss 和 mAP。重点看mAP50-95mAP50,前者更严格。如果cls_loss一直不降,检查标签类别是否对;如果box_loss震荡,把lr0降到 0.005 再试。

4.2 用损失函数曲线判断过拟合与欠拟合

训练完成后,runs_factory/exp1下会有results.csvresults.png。我一般会画一张损失曲线图,直观判断模型状态。

import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("runs_factory/exp1/results.csv") df.columns = df.columns.str.strip() plt.figure(figsize=(10, 5)) plt.plot(df["epoch"], df["train/box_loss"], label="train box loss") plt.plot(df["epoch"], df["val/box_loss"], label="val box loss") plt.plot(df["epoch"], df["train/cls_loss"], label="train cls loss") plt.plot(df["epoch"], df["val/cls_loss"], label="val cls loss") plt.xlabel("epoch") plt.ylabel("loss") plt.legend() plt.savefig("loss_curve.png", dpi=150)

逻辑说明:训练 loss 和验证 loss 同时下降且接近,说明拟合正常;训练 loss 继续降但验证 loss 抬头,就是过拟合,需要加数据或加增强;两条都居高不下,是欠拟合,检查学习率或模型容量。危险区域闯入场景里,过拟合的典型表现是验证集 mAP 高但实际车间误报多,因为训练集场景太单一。

注意:不要只看 mAP 高就上线,一定要用一段没参与训练的车间视频做推理测试,看误报和漏报。

4.3 模型导出与推理速度优化

训练完的best.pt可以直接用于推理,但如果要部署到边缘设备,可以导出 ONNX 或 TensorRT。CPU 部署建议导出 ONNX,用 OpenCV DNN 或 ONNX Runtime 加载,比 PyTorch 直接推理快 20% 到 30%。

yolo export model=runs_factory/exp1/weights/best.pt format=onnx imgsz=640

导出后得到best.onnx,推理时把model=best.pt换成model=best.onnx即可。如果部署到 RK3588 或 Hi3516CV610 这类板端,需要走对应的模型转换工具链,流程更复杂,建议先用 PC 验证效果再上板。

5. 危险区域判断逻辑与可视化界面实现

5.1 多边形区域定义与脚底点判断

检测到人之后,怎么判断「闯入」?我一般用脚底点,也就是检测框底边的中点。相比用框中心点,脚底点更符合地面区域的实际位置,人站在区域外但身体前倾时,中心点可能已经在区域内,脚底点不会误判。

区域用多边形表示,支持任意形状,比如冲压机周围的 L 形警戒区。判断点是否在多边形内,用射线法,OpenCV 自带pointPolygonTest

import cv2 import numpy as np # 定义危险区域多边形,坐标按实际画面比例设置 danger_zone = np.array([[200, 300], [500, 300], [500, 600], [200, 600]], dtype=np.int32) def is_intrusion(box, zone): # box 格式 [x1, y1, x2, y2] x1, y1, x2, y2 = box # 脚底点:底边中点 foot_x = (x1 + x2) / 2.0 foot_y = y2 # pointPolygonTest 返回正数表示在内部 result = cv2.pointPolygonTest(zone, (foot_x, foot_y), False) return result >= 0

逻辑说明:danger_zone是四个顶点,实际使用时可以用鼠标在界面上点选生成。pointPolygonTest的第三个参数False表示只返回距离符号,不返回具体距离,速度更快。如果返回大于等于 0,说明脚底点在区域内,触发闯入报警。

参数上要注意:区域坐标必须和推理时的图像尺寸一致。如果推理时做了 resize,区域坐标也要按比例缩放。我一般会在界面上让用户直接在原始分辨率上画区域,推理前再把区域缩放到模型输入尺寸,避免坐标错位。

5.2 可视化界面:用 PyQt5 还是 Web 端

源码里通常带一个可视化界面,常见的是 PyQt5 或 Gradio。PyQt5 适合本地桌面运行,能直接调摄像头,延迟低;Gradio 适合浏览器访问,方便演示但延迟稍高。如果是毕设答辩,PyQt5 更稳,因为不依赖网络。

界面核心功能就三块:视频显示、区域绘制、报警日志。视频显示用 OpenCV 读帧,YOLOv8 推理后画框和区域,闯入时框变红并记录时间。区域绘制用鼠标事件收集顶点,右键闭合。报警日志写到一个列表里,支持导出 CSV。

# 简化版 PyQt5 视频循环逻辑 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break results = model(frame, imgsz=640, verbose=False) for r in results: for box in r.boxes: x1, y1, x2, y2 = map(int, box.xyxy[0]) if is_intrusion([x1, y1, x2, y2], danger_zone): cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) # 记录报警 else: cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.polylines(frame, [danger_zone], True, (0, 255, 255), 2) cv2.imshow("Factory Safety", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break

这段代码把检测、区域判断、绘制串起来。verbose=False关掉 YOLO 的日志输出,避免刷屏。实际界面里会把cv2.imshow换成 Qt 的 QLabel 显示,报警日志写到表格控件。

5.3 报警去抖与多目标处理

实际产线上,人走过区域边缘时可能连续几帧触发又消失,如果每帧都报警,日志会爆炸。我一般加一个计数器:连续 3 帧检测到闯入才触发一次报警,报警后 5 秒内不重复报同一目标。多目标时给每个框分配一个简单 ID,用 IOU 匹配前后帧,避免同一个人被反复计数。

# 简单去抖逻辑 intrusion_counter = 0 alarm_cooldown = 0 if is_intrusion(box, danger_zone): intrusion_counter += 1 else: intrusion_counter = 0 if intrusion_counter >= 3 and alarm_cooldown == 0: trigger_alarm() alarm_cooldown = 50 # 约 5 秒,按 10FPS 算 if alarm_cooldown > 0: alarm_cooldown -= 1

参数350根据实际帧率调整。帧率低就减小计数阈值,帧率高就增大冷却帧数。这个逻辑不复杂,但不加的话演示时会被频繁报警搞得很尴尬。

6. 避坑与排查:部署危险区域识别系统时最容易翻车的 5 个点

6.1 现象:训练 loss 正常但推理时一个框都没有

原因通常是推理时的图像预处理和训练时不一致。YOLOv8 训练时默认做了 letterbox 填充,推理时如果直接 resize 会改变宽高比,导致目标变形。解决方法是推理时也用model.predict的默认预处理,不要自己手动 resize 后再送入模型。如果必须手动处理,确保保持宽高比并填充灰边。

6.2 现象:区域判断总是误报,人明明在区域外

先检查区域坐标和推理图像尺寸是否匹配。常见情况是界面按 1920x1080 画的区域,但推理时把帧缩到了 640x640,坐标没同步缩放。解决方法是统一在原始分辨率上做区域判断,或者把区域坐标按缩放比例同步变换。另一个原因是用了框中心点而不是脚底点,改成脚底点后误报会明显减少。

6.3 现象:CPU 推理太慢,视频卡成幻灯片

YOLOv8n 在 CPU 上单帧 100 毫秒左右,如果同时开可视化界面和视频解码,很容易掉到 2 到 3 FPS。解决方法是把推理分辨率降到 416 或 320,或者跳帧推理,每 3 帧检测一次,中间帧沿用上一次结果。如果还慢,导出 ONNX 用 ONNX Runtime 推理,开启多线程。

6.4 现象:换一个车间后模型完全失效

这是过拟合到训练场景的典型表现。训练集里如果只有白天、固定角度、穿同色工服的人,换到夜间或逆光场景,模型召回率会暴跌。解决方法是在数据集里加入目标场景的样本,至少 500 张,覆盖不同光照和角度。如果来不及重新标,先用现有模型加一个低阈值推理,把误报和漏报的帧截下来人工筛选,再增量训练。

6.5 现象:可视化界面打包成 exe 后打不开

PyQt5 打包时经常漏掉 OpenCV 的依赖库。用 PyInstaller 打包时加--hidden-import=cv2--collect-all ultralytics,否则运行时找不到模型或 DLL。另一个坑是模型权重文件没有一起打包,exe 在别的机器上找不到best.pt。解决方法是用--add-data把权重和配置文件一起打进去,运行时用sys._MEIPASS定位路径。

7. 进阶技巧:用区域掩码和轨迹过滤把误报再降一半

如果你已经把基础链路跑通,想让系统在车间里真正可用,我建议加两个东西:区域掩码和轨迹过滤。区域掩码是把危险区域从画面里裁出来单独做检测,减少区域外人员的干扰;轨迹过滤是记录每个人连续多帧的位置,只有从区域外进入区域内才算闯入,已经在区域内的人不重复报警。

先讲区域掩码。YOLOv8 支持classes参数只检测特定类别,但不支持只检测特定区域。我的做法是在推理前把区域外的像素涂黑,或者用 ROI 裁剪。涂黑更简单,但会改变画面统计特性,可能影响模型。ROI 裁剪更干净,但区域坐标要重新映射。我一般用 ROI 裁剪,因为危险区域通常只占画面一小部分,裁出来还能提高小目标分辨率。

# ROI 裁剪推理,区域外不检测 x, y, w, h = cv2.boundingRect(danger_zone) roi = frame[y:y+h, x:x+w] results = model(roi, imgsz=640, verbose=False) # 检测框坐标映射回原图 for r in results: for box in r.boxes: x1, y1, x2, y2 = map(int, box.xyxy[0]) x1 += x; x2 += x; y1 += y; y2 += y # 后续判断和绘制

这段代码把危险区域的外接矩形裁出来推理,检测框再映射回原图。好处是区域外的人不会被检测,减少计算量和误报。参数上注意boundingRect返回的是整数坐标,裁剪时要确保不越界。

再讲轨迹过滤。简单做法是给每个检测框分配一个 ID,用 IOU 匹配前后帧。如果某个 ID 的脚底点从区域外变成区域内,才触发报警;如果一开始就在区域内,只记录不报警。这样能过滤掉在区域内工作的人,只抓真正闯入的。

# 简化轨迹过滤:记录上一帧脚底点是否在区域内 track_history = {} # id -> last_inside def check_intrusion_with_track(track_id, foot_point, zone): inside = cv2.pointPolygonTest(zone, foot_point, False) >= 0 last_inside = track_history.get(track_id, False) track_history[track_id] = inside # 只有从外到内才报警 return inside and not last_inside

这个逻辑需要配合目标跟踪,YOLOv8 本身不带跟踪,可以用 ByteTrack 或简单的 IOU 匹配。如果不想引入跟踪库,用检测框的 IOU 做前后帧关联也能凑合,但人走动快时容易断。我一般会加一个最大丢失帧数,超过 10 帧没匹配上就删除轨迹。

最后说一个验证方法:不要只看 mAP,用一段 10 分钟的车间视频跑一遍,统计误报次数和漏报次数。误报包括区域外人员被误判、非人员目标被误判;漏报包括真实闯入没报警。我自己的经验是,mAP50 到 0.9 以上,实际误报仍然可能每小时好几次,必须靠区域逻辑和轨迹过滤压下去。这套系统值不值得做,取决于你能不能接受「检测模型只负责找人,业务逻辑负责判断」这个分工。我踩过最大的坑就是试图让模型直接学「闯入」行为,结果标注成本翻倍,效果还差。把问题拆开,每一层都简单可控,才是工程落地的习惯。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 18:16:20

远程3D渲染全攻略:GPU算力云、远程桌面与硬件选型实战指南

远程3D渲染这个词&#xff0c;这几年被提得越来越频繁。2026年再看这件事&#xff0c;我觉得核心就一句话&#xff1a;把算力留在机房&#xff0c;人回家。过去做三维设计的人&#xff0c;基本被一台高性能工作站绑在工位上&#xff0c;机器在哪&#xff0c;人就得在哪。现在不…

作者头像 李华
网站建设 2026/9/24 18:16:00

Windows 开机自动录屏 8 种方案详解:从任务计划程序到 FFmpeg 实战

Windows 上实现开机自动录屏&#xff0c;听上去是个很小的需求&#xff0c;真做起来却有一堆讲究。我最近因为要给一台无人值守的机器做操作记录&#xff0c;把 Win10 22H2 和 Win11 23H2 上能用的开机自动录屏方案挨个测了一遍&#xff0c;发现最大的坑不是"找不到方法&q…

作者头像 李华
网站建设 2026/9/24 18:15:58

AI提效实战:DeepSeek、Kimi、Cursor三款工具组合使用指南

每天被各类消息、文档、报表轮番轰炸&#xff0c;加班到八九点成了不少职场人的日常。我大概花了三周时间&#xff0c;把市面上能叫得出名字的AI工具挨个用了一遍&#xff0c;最后真正留在工作流里、每天都离不开的其实只有三款。它们不是那种“看起来很酷但用不上”的玩具&…

作者头像 李华
网站建设 2026/9/24 18:15:16

JavaWeb金融借贷系统实战:Servlet+JDBC实现P2P全流程

简介&#xff1a;本资源是一套基于JavaWeb开发的金融借贷系统&#xff08;P2P小额贷款管理平台&#xff09;&#xff0c;专为计算机相关专业本科生毕业设计及Java初学者项目实战打造&#xff0c;覆盖融资产品管理、贷款申请全流程、新闻资讯发布等核心业务场景&#xff0c;兼顾…

作者头像 李华
网站建设 2026/9/24 18:15:10

个人微信API二次开发:如何实现多微信统一管理?

多微信号运营&#xff0c;若只是多台手机人工切换&#xff0c;规模上不去&#xff1b;若在一台电脑上硬多开再键鼠群控&#xff0c;又和正式节点抢会话。个人微信API二次开发更常见的模型是&#xff1a;一个&#xff08;或多个&#xff09;Token 下挂多个执行节点&#xff0c;每…

作者头像 李华