
简介这份资源面向计算机、人工智能、自动化等专业的在校学生与教师提供一套基于YOLOv8的智慧工厂危险区域闯入识别系统完整方案可用于毕业设计、课程设计或大作业。压缩包共8个文件约15.91MB包含3个Python脚本、3个模型权重文件与2个说明文本分别对应可视化界面、模型训练与视频检测推理等核心环节部署流程简单开箱即可运行。项目附带完整数据集与可视化页面能够生成核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图便于答辩展示与结果分析。目前已有30人学习关注。读者可直接获得经过测试的源码、训练好的权重、数据集与部署说明既能快速复现危险区域闯入识别效果也可在此基础上修改扩展功能适合作为毕设保底项目或入门目标检测的实践案例。1. 智慧工厂危险区域闯入识别为什么YOLOv8成了产线安全的第一道防线在智慧工厂的落地场景里危险区域闯入识别几乎是每个集成商都会碰到的需求冲压机床周边、高压配电柜前方、AGV 充电区、高温熔炉半径内这些区域一旦有人员误入轻则停机停产重则人身伤害。传统做法靠物理围栏加红外对射问题是误报率高、无法区分人和叉车、也没法留证据。用 YOLOv8 做视觉闯入识别本质是把「区域入侵检测」拆成两个可工程化的子问题先稳定检测出画面里的人再用多边形或矩形区域做空间判定。这套方案适合做毕设或课程设计的同学也适合工厂里想快速验证视觉安全方案的工程师——因为 YOLOv8 的预训练权重开箱即用数据集标注成本可控可视化界面又能直接演示给非技术方看。我见过太多人卡在环境配置和数据集格式转换上其实真正跑通一条「训练→推理→区域判定→界面展示」的链路比想象中短得多。2. 从零搭起 YOLOv8 闯入识别的最小可运行环境2.1 环境配置CPU 版本也能先跑通别一上来就折腾 CUDA很多人第一反应是装 GPU 环境结果卡在驱动版本和 CUDA 兼容性上三天没跑出一行结果。我的建议是先用 CPU 版本把整条链路跑通确认代码逻辑没问题再换 GPU 加速训练。Ubuntu 20.04 和 CentOS 7 都能装Windows 下用 conda 建虚拟环境同样可行。核心依赖就三个ultralytics、opencv-python、torch。注意 torch 的 CPU 版本和 GPU 版本安装命令不同装错了会报Torch not compiled with CUDA enabled。# 创建虚拟环境Python 版本建议 3.8 到 3.10 conda create -n yolov8_factory python3.9 -y conda activate yolov8_factory # 安装 CPU 版本 torch先确认能跑通再换 GPU pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics 和可视化依赖 pip install ultralytics opencv-python pillow matplotlib这段命令的逻辑是先隔离环境避免污染系统 Python再装 CPU 版 torch 降低首次运行门槛最后装 ultralytics 这个包——它同时提供了 YOLOv8 的训练、推理和导出接口。参数上唯一要注意的是 Python 版本3.11 以上某些依赖轮子还没跟上3.9 最稳。装完后用yolo checks验证能看到环境摘要就说明基础通了。2.2 数据集准备Labelme 标注转 YOLO 格式的完整脚本危险区域闯入识别的数据集通常只有一类目标person。但工厂场景下的人可能戴安全帽、穿反光衣、被机器部分遮挡所以标注时要尽量覆盖这些形态。用 Labelme 标注会生成 JSON 文件而 YOLOv8 需要的是每张图对应一个 txt每行格式为class_id x_center y_center width height且坐标要归一化到 0 到 1 之间。下面这个转换脚本我用了很多次直接改路径就能跑。import json import os from pathlib import Path def labelme_to_yolo(json_dir, output_dir, class_names): json_dir: Labelme 标注文件所在目录 output_dir: 输出 txt 标签的目录 class_names: 类别名称列表如 [person] json_dir Path(json_dir) output_dir Path(output_dir) output_dir.mkdir(parentsTrue, exist_okTrue) for json_file in json_dir.glob(*.json): with open(json_file, r, encodingutf-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_names: continue class_id class_names.index(label) 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_center (x_min x_max) / 2.0 / img_w y_center (y_min y_max) / 2.0 / img_h width (x_max - x_min) / img_w height (y_max - y_min) / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) # 写入同名 txt txt_path output_dir / (json_file.stem .txt) with open(txt_path, w) as f: f.write(\n.join(lines)) print(f转换完成共处理 {len(list(json_dir.glob(*.json)))} 个文件) # 使用示例 labelme_to_yolo( json_dir./raw_annotations, output_dir./labels, class_names[person] )逻辑说明脚本遍历每个 JSON读取图像宽高用于归一化把 Labelme 的多边形点集转成外接矩形再按 YOLO 格式写入 txt。参数上class_names必须和后续训练时的data.yaml里的names顺序一致否则类别会错位。转换完成后要检查两点一是空 txt 文件表示该图没有目标训练时会被当作背景图这是允许的二是坐标是否都在 0 到 1 之间超出说明标注时点到了图像外面。2.3 训练配置data.yaml 写法和三个必调参数数据集目录结构建议按 YOLOv8 官方推荐来images/train、images/val、labels/train、labels/val四个文件夹。然后写一个data.yamlpath: /home/user/factory_dataset train: images/train val: images/val names: 0: person训练命令用命令行或 Python 脚本都行我习惯用脚本方便记录参数from ultralytics import YOLO model YOLO(yolov8n.pt) # 从预训练权重开始小模型适合快速验证 results model.train( datadata.yaml, epochs100, imgsz640, batch16, lr00.01, patience20, devicecpu # 有 GPU 改成 0 )三个必调参数imgsz决定输入分辨率工厂监控画面通常 1080P但训练时缩到 640 能在精度和速度间取得平衡batch在 CPU 上设 8 或 16太大内存扛不住patience是早停轮数设 20 表示验证集损失 20 轮不降就停避免过拟合。lr0初始学习率默认 0.01 对小数据集够用如果 loss 震荡厉害降到 0.001。3. 危险区域判定逻辑从检测框到闯入报警的工程实现3.1 多边形区域定义与点框相交判定检测出人只是第一步真正决定是否报警的是「人有没有进入危险区域」。工厂里的危险区域往往不是矩形比如机械臂旋转半径是扇形配电柜前方是梯形。所以要用多边形定义区域再判断检测框的底边中心点是否落在多边形内——用底边中心点而不是框中心是因为人脚的位置才代表实际站立点。import cv2 import numpy as np def is_inside_zone(bbox, polygon): bbox: [x1, y1, x2, y2] 检测框 polygon: np.array([[x1,y1], [x2,y2], ...]) 多边形顶点 返回: 底边中心点是否在多边形内 x1, y1, x2, y2 bbox # 取底边中心点 foot_point ((x1 x2) / 2, y2) # cv2.pointPolygonTest 返回正数表示在内负数在外0 在边上 result cv2.pointPolygonTest(polygon, foot_point, False) return result 0 # 定义一个梯形危险区域 danger_zone np.array([ [200, 300], [500, 300], [600, 600], [100, 600] ], dtypenp.int32)逻辑说明pointPolygonTest是 OpenCV 自带的几何判定函数第三个参数False表示只返回位置关系不返回距离。参数上要注意多边形顶点顺序必须是顺时针或逆时针连续排列不能交叉否则判定结果会乱。实际部署时这个多边形坐标应该做成可配置的因为摄像头安装位置一变区域坐标就得重新标定。3.2 可视化界面用 PyQt5 做一个能演示的闯入报警窗口毕设和课程设计最需要的就是「能演示」。一个简单的 PyQt5 界面左边显示视频流和检测框右边显示报警日志和区域开关足够让答辩老师看明白。核心是用 QTimer 定时抓帧把 YOLOv8 推理结果画上去。import sys import cv2 from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer from ultralytics import YOLO import numpy as np class FactoryMonitor(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(危险区域闯入识别系统) self.model YOLO(runs/detect/train/weights/best.pt) self.cap cv2.VideoCapture(0) # 换成视频文件路径也行 self.danger_zone np.array([[200,300],[500,300],[600,600],[100,600]], dtypenp.int32) self.label QLabel() self.btn QPushButton(暂停/继续) self.btn.clicked.connect(self.toggle) layout QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.btn) container QWidget() container.setLayout(layout) self.setCentralWidget(container) self.timer QTimer() self.timer.timeout.connect(self.update_frame) self.timer.start(30) # 约 33fps def toggle(self): if self.timer.isActive(): self.timer.stop() else: self.timer.start(30) def update_frame(self): ret, frame self.cap.read() if not ret: return results self.model(frame, verboseFalse)[0] alarm False for box in results.boxes: x1, y1, x2, y2 map(int, box.xyxy[0]) conf float(box.conf[0]) if conf 0.5: continue foot ((x1x2)//2, y2) inside cv2.pointPolygonTest(self.danger_zone, foot, False) 0 color (0,0,255) if inside else (0,255,0) if inside: alarm True cv2.rectangle(frame, (x1,y1), (x2,y2), color, 2) cv2.putText(frame, fperson {conf:.2f}, (x1,y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.polylines(frame, [self.danger_zone], True, (0,255,255), 2) if alarm: cv2.putText(frame, ALARM: INTRUSION, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0,0,255), 3) rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qt_img QImage(rgb.data, w, h, ch*w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qt_img)) if __name__ __main__: app QApplication(sys.argv) win FactoryMonitor() win.show() sys.exit(app.exec_())逻辑说明QTimer 每 30 毫秒触发一次 update_frame抓帧后送入模型推理遍历检测框判断脚点是否在危险区域内是则画红框并显示 ALARM。参数上conf 0.5是置信度过滤工厂场景建议设 0.5 到 0.6太低会误报太高会漏检远处的人。self.cap cv2.VideoCapture(0)里的 0 是默认摄像头换成 RTSP 地址就能接网络摄像头。4. 避坑与排查训练和部署中最容易翻车的五个地方4.1 现象训练 loss 一直不降mAP 始终在 0.1 以下原因通常是 data.yaml 里的路径写错了或者 labels 目录和 images 目录没有对应上。YOLOv8 找不到标签文件时不会报错而是把所有图当背景训练loss 自然降不下去。解决方法是训练前用model.train的verboseTrue看数据集加载数量如果train和val的图片数为 0 就是路径问题。另外检查 txt 文件名是否和图片名完全一致包括大小写。4.2 现象推理时检测框位置偏移严重框比人小一圈这是标注格式转换时坐标没归一化或者归一化时除错了宽高。Labelme 的坐标是绝对像素值YOLO 需要除以图像宽高。如果转换脚本里把 x 除以了高度、y 除以了宽度框就会错位。排查方法是拿一张训练集里的图跑推理对比标注框和预测框如果偏移方向有规律就是归一化轴搞反了。4.3 现象CPU 推理速度只有 2 到 3 FPS界面卡死YOLOv8n 在 CPU 上单帧推理大约 80 到 150 毫秒加上 PyQt5 界面刷新和画框30 毫秒的定时器根本来不及。解决办法是把推理放到独立线程或者降低输入分辨率到 320再或者换 yolov8n 而不是 s/m/l。如果必须实时考虑用 OpenVINO 导出模型CPU 上能提速 2 到 3 倍。4.4 现象危险区域判定时人明明在外面却报警多边形顶点顺序错了导致pointPolygonTest把区域内部判定成了外部。OpenCV 要求多边形顶点按顺时针或逆时针连续排列不能交叉。排查方法是用cv2.polylines把多边形画出来肉眼看形状是否和预期一致。如果画出来是蝴蝶结形状就是顶点顺序交叉了。4.5 现象换了一个摄像头后所有检测框都偏了不同摄像头的视场角和安装高度不同同一个多边形坐标在不同画面里对应的实际物理区域不一样。这不是代码 bug是标定问题。解决方法是每个摄像头单独配置一套区域坐标或者做一个标定界面让用户手动点选多边形顶点。我一般会在配置文件里按摄像头 ID 存多套区域坐标。5. 进阶技巧用跟踪 ID 过滤误报和导出 ONNX 提速5.1 用 ByteTrack 给每个人分配 ID连续闯入才报警单帧检测有个玄学问题偶尔一帧把机器上的反光误检成人就会触发一次报警。加跟踪后可以要求同一个人连续 5 帧都在危险区域内才报警误报率大幅下降。Ultralytics 内置了 ByteTrack只需要在推理时加trackerbytetrack.yaml。from ultralytics import YOLO model YOLO(best.pt) results model.track(sourcefactory.mp4, trackerbytetrack.yaml, persistTrue) for r in results: if r.boxes.id is not None: ids r.boxes.id.cpu().numpy() boxes r.boxes.xyxy.cpu().numpy() for track_id, box in zip(ids, boxes): print(fID {track_id}: {box})逻辑说明persistTrue表示在视频流中保持跟踪状态r.boxes.id就是每个人的跟踪 ID。参数上 ByteTrack 的配置文件可以调track_high_thresh和track_low_thresh工厂场景建议把低阈值调高一点减少 ID 切换。5.2 导出 ONNX 并在 CPU 上提速训练完的 .pt 文件在 CPU 上推理慢导出 ONNX 后用 onnxruntime 能快不少。导出命令一行yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640导出后在 Python 里用 onnxruntime 加载推理注意输入需要归一化到 0 到 1 并转成 NCHW 格式。我实测 yolov8n 在 i5 上从 120ms 降到 60ms 左右对演示场景够用了。5.3 一个容易被忽略的细节报警日志要落盘演示时报警一闪而过答辩老师问「刚才那次报警是什么时候」就答不上来。加一个简单的日志写入每次报警记录时间戳和跟踪 ID存成 CSV。这个习惯是我踩过坑之后养成的——有次工厂那边要查一周前的闯入记录结果什么都没存只能重新部署。希望帮到你。本文还有配套的精品资源点击获取