
简介本资源是华南理工大学大学生创新创业训练计划项目成果——一套面向高校安防场景的智能校园安全监控系统实现方案聚焦于利用AI技术解决校园异常行为实时检测与预警难题适用于计算机视觉初学者、深度学习实践者及智慧校园系统开发者。压缩包共213个文件含89个标注XML文件用于YOLOv5训练数据集、66个Java后端逻辑与告警模块代码、28张测试图像及界面截图、4个说明类TXT/HTML文档含部署指南与功能说明以及附赠的项目报告DOCX和源码主目录DaChuang-main整体大小为3.03MB。已有89人下载学习资源结构完整涵盖数据标注规范、YOLOv5模型训练配置、OpenCV图像预处理流程、异常行为判定逻辑及声光预警集成方案特别适合复现端到端AI安防项目、理解目标检测在真实监控场景中的工程落地细节。1. 项目概述与核心价值去年我们团队在华南理工大学完成了一个大学生创新创业训练计划项目核心是构建一个“智能校园安全监控系统”。这个想法源于一个很实际的痛点传统的校园监控摄像头数量庞大但基本依赖于保安人员24小时盯屏人力成本高且极易因疲劳导致漏报。我们想做的就是让摄像头“看懂”画面自动识别打架斗殴、人员聚集、攀爬围墙、异常滞留等危险行为并及时发出预警。整个系统的技术栈非常明确就是基于深度学习与计算机视觉。我们选择了当时在目标检测领域表现和易用性俱佳的YOLOv5作为核心检测算法再结合OpenCV这套老牌且强大的图像处理库来完成从视频流接入、图像预处理、目标检测到行为分析、预警推送的全链路。这不是一个纯理论的模型训练项目而是一个软硬件结合、需要实际部署和调优的工程系统。最终我们成功搭建了一套原型能够对测试视频中的多种异常行为进行实时检测与报警验证了技术路线的可行性。这篇文章我就以一个亲历者的身份来详细拆解这个项目的完整实现过程。我会重点分享我们为什么选YOLOv5和OpenCV如何准备和标注自己的校园场景数据集模型训练与优化的具体细节以及将算法模型集成到实际视频流处理管道中遇到的种种“坑”和解决方案。无论你是对AI落地应用感兴趣的学生还是正在寻找计算机视觉项目灵感的开发者相信这份来自一线的实战记录都能给你带来直接的参考。2. 整体系统架构与设计思路2.1 核心需求与场景定义在动手写代码之前我们花了大量时间明确“智能监控”到底要智能在哪里。我们调研了校园安保部门的实际工作记录归纳出以下几类高优先级、且适合用视觉算法检测的异常行为打架斗殴检测核心是检测多人之间快速的、非正常的肢体接触与剧烈运动。这不仅仅是检测到“人”还要分析人与人之间的互动关系。区域入侵与攀爬检测针对围墙、楼顶、配电房等禁止进入的区域。需要划定电子围栏ROI并检测是否有人员进入或攀爬。异常聚集检测在楼道、校门口等区域短时间内人员密度异常增高可能存在安全隐患或群体事件。长时间滞留检测在深夜的教学楼走廊、停车场角落等区域单人长时间静止不动可能意味着突发疾病或可疑行为。物品遗留检测在图书馆、食堂等公共场所检测是否有包裹、箱子等物品被长时间遗弃。定义清楚场景后我们意识到所有高级行为分析的基础都是快速、准确地检测出画面中的“人”这个目标。因此一个高性能的目标检测模型是整个系统的基石。2.2 技术选型为什么是YOLOv5与OpenCV当时可选的算法很多比如两阶段的Faster R-CNN单阶段的SSD、YOLO系列等。我们最终锁定YOLOv5主要基于以下几点工程化考量速度与精度的平衡校园监控需要实时或近实时处理YOLOv5在保持较高检测精度mAP的同时其推理速度远超两阶段模型在普通的服务器甚至边缘设备上都能达到可用的帧率。工程化友好YOLOv5的代码库Ultralytics版非常清晰提供了从训练、验证、测试到导出的完整工具链。其模型导出格式如TorchScript, ONNX, CoreML丰富便于后续部署到不同平台。社区活跃资源丰富遇到问题容易找到解决方案和预训练模型这对于学生项目快速启动至关重要。而选择OpenCV则是因为它在视频流处理、图像预处理/后处理、图形绘制以及跨平台部署方面无可替代视频流处理cv2.VideoCapture可以轻松接入RTSP流监控摄像头主流协议、视频文件或本地摄像头。图像处理管道检测前需要对图像进行缩放、归一化、色彩空间转换BGR2RGB检测后需要画框、标标签、画ROI区域。OpenCV的接口高效且统一。轻量级与跨平台C核心带来的高性能以及完善的Python绑定使得它既能用于快速原型开发也能集成到C生产环境中。我们的架构可以简化为OpenCV负责“眼睛”获取视频流和“手”画图、报警YOLOv5负责“大脑”识别目标。高级行为分析逻辑则在我们自己编写的业务层中实现。2.3 系统工作流程整个系统的运行时流程是一个清晰的流水线视频流输入通过OpenCV从网络摄像头、RTSP流或视频文件读取帧。图像预处理将帧缩放到模型输入尺寸如640x640进行归一化像素值/255.0并组织成模型需要的张量格式。目标检测推理将预处理后的图像张量送入YOLOv5模型得到所有检测到的目标信息包括边界框坐标、置信度、类别ID。后处理与过滤应用非极大值抑制NMS去除重叠框并根据置信度阈值如0.5过滤掉不可信的检测结果。行为分析与事件判断这是我们的核心业务逻辑。基于当前帧和过去若干帧的检测结果人的位置、速度、轨迹判断是否触发预设的异常行为规则。预警与可视化如果触发预警系统会通过OpenCV在画面上高亮显示事件区域、打印警告文字同时可以通过网络API、邮件或消息队列将警报信息发送给后台或保安终端。输出与循环将处理后的画面显示在监控屏幕上或保存为新的视频文件然后循环处理下一帧。3. 数据集构建与模型训练实战3.1 校园场景数据采集与标注没有数据再好的算法也是无米之炊。校园场景有其特殊性学生穿着校服、便服、光照变化白天、夜晚、阴雨、摄像头角度俯视、平视多样。直接使用公开数据集如COCO的模型在具体场景下性能会打折扣。我们的数据来源主要有两个公开监控视频片段从一些开源的安全监控数据集中筛选出与校园环境类似的片段。自采视频在征得同意并确保隐私的前提下在校园内部分区域拍摄了一些模拟异常行为的视频如模拟聚集、快跑。标注工具我们选择了LabelImg和Roboflow。LabelImg本地化部署适合小规模启动Roboflow在线平台则提供了数据增强、版本管理和格式转换的一站式服务后期效率更高。标注时只标注“person”这一类因为我们的核心是人的行为。注意数据标注的规范性至关重要。框要紧贴人体避免包含过多背景对于遮挡严重、无法判断为人的目标选择不标或标为“difficult”。我们初期因为框得比较随意导致模型学会了把一些背景柱子也识别为人后期清洗数据花了很大力气。3.2 YOLOv5模型训练详解我们使用的是Ultralytics维护的YOLOv5代码库。以下是训练的关键步骤和参数解析环境配置创建Python虚拟环境安装torch建议使用CUDA版本以利用GPU加速、torchvision以及requirements.txt中的其他依赖。数据格式准备YOLOv5需要特定的目录结构和.txt标注文件。每个图像对应一个.txt文件每行格式为class_id x_center y_center width height坐标是归一化后的除以图像宽高。我们使用Roboflow直接导出为YOLOv5格式省去了转换的麻烦。配置文件修改数据配置文件data/campus.yaml指定训练/验证图像的路径、类别数量和类别名称。# campus.yaml path: ../datasets/campus train: images/train val: images/val nc: 1 # number of classes names: [person]模型配置文件选择YOLOv5s小、YOLOv5m中、YOLOv5l大等不同尺寸的模型。我们从YOLOv5s开始在速度和精度间取得较好平衡。开始训练执行核心训练命令。python train.py --img 640 --batch 16 --epochs 100 --data data/campus.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name campus_person_det--img 640输入图像尺寸。更大的尺寸如1280可能提升对小目标的检测能力但会显著增加计算量和内存消耗。--batch 16批大小。根据GPU内存调整内存不足时需调小。--epochs 100训练轮数。需要观察训练损失和验证指标曲线防止过拟合。--weights yolov5s.pt加载预训练权重在COCO上训练过的这是提升模型性能和收敛速度的关键即迁移学习。训练监控与评估训练开始后YOLOv5会启动本地Web服务默认http://localhost:6006可以通过TensorBoard查看损失曲线、精度mAP0.5等指标的变化。我们特别关注mAP0.5:0.95它衡量了在不同IoU阈值下的平均精度更能综合反映模型性能。3.3 模型优化与调参心得直接训练出来的模型往往不是最优的我们进行了多轮调优学习率调整YOLOv5默认使用余弦退火学习率调度器。我们发现当验证集精度在后期停滞时尝试稍微降低初始学习率如从0.01降到0.001有时能带来提升。数据增强YOLOv5默认开启了Mosaic、随机仿射变换、色彩抖动等增强。对于监控场景我们额外强调了模拟不同光照亮度、对比度调整和随机遮挡模拟树木、柱子遮挡这极大地提升了模型在复杂环境下的鲁棒性。超参数进化YOLOv5提供了一个超参数进化脚本evolve.py可以自动搜索一组更好的超参数如学习率、损失函数权重等。我们跑了一次大约花了1天时间最终mAP提升了约2%对于性能瓶颈明显的场景值得一试。解决类别不平衡我们的数据集中“人”是唯一类别不存在不平衡。但如果要检测“人”和“车”且“车”的样本很少就需要在数据配置文件中设置class_weights或在损失函数中考虑。实操心得不要盲目追求大模型。我们对比了YOLOv5s和YOLOv5l在测试集上的表现。YOLOv5l的mAP高了3%但推理速度慢了近4倍。在部署到一台老旧的工控机上时YOLOv5s能勉强达到15 FPS而YOLOv5l只有不到4 FPS无法满足实时性。最终我们选择了YOLOv5s并通过后续的模型剪枝和量化进一步提升了速度。4. 系统集成与核心功能实现4.1 视频流处理管道搭建这是将训练好的模型投入使用的第一步。我们编写了一个核心的VideoProcessor类。import cv2 import torch from models.experimental import attempt_load from utils.general import non_max_suppression, scale_boxes class VideoProcessor: def __init__(self, model_path, rtsp_url, conf_thres0.5, iou_thres0.45): self.device torch.device(cuda if torch.cuda.is_available() else cpu) self.model attempt_load(model_path, deviceself.device) self.model.eval() # 设置为评估模式 self.conf_thres conf_thres self.iou_thres iou_thres self.cap cv2.VideoCapture(rtsp_url) self.frame_width int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) self.frame_height int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) def preprocess(self, frame): 将OpenCV的BGR图像预处理为YOLOv5输入张量 img cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img cv2.resize(img, (640, 640)) img img / 255.0 # 归一化 img img.transpose(2, 0, 1) # HWC to CHW img torch.from_numpy(img).to(self.device).float() img img.unsqueeze(0) # 增加批次维度 return img def detect(self, img_tensor): 执行推理和后处理 with torch.no_grad(): pred self.model(img_tensor)[0] pred non_max_suppression(pred, self.conf_thres, self.iou_thres, classesNone, agnosticFalse) return pred def postprocess(self, detections, original_frame): 将检测框映射回原图坐标并绘制结果 results [] if detections[0] is not None: det detections[0] # 将框的坐标从640x640缩放回原始图像尺寸 det[:, :4] scale_boxes((640, 640), det[:, :4], original_frame.shape).round() for *xyxy, conf, cls in det: label fperson {conf:.2f} cv2.rectangle(original_frame, (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])), (0, 255, 0), 2) cv2.putText(original_frame, label, (int(xyxy[0]), int(xyxy[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2) results.append({bbox: xyxy, conf: conf}) return original_frame, results def run(self): 主循环 while self.cap.isOpened(): ret, frame self.cap.read() if not ret: break img_tensor self.preprocess(frame) detections self.detect(img_tensor) processed_frame, person_results self.postprocess(detections, frame) # 在此处调用行为分析模块传入person_results # self.behavior_analyzer.analyze(person_results, processed_frame) cv2.imshow(Smart Campus Surveillance, processed_frame) if cv2.waitKey(1) 0xFF ord(q): break self.cap.release() cv2.destroyAllWindows()4.2 关键行为分析算法实现基于上述得到每一帧的person_results人员检测框列表我们实现了几个核心行为分析模块。4.2.1 打架斗殴检测我们采用了一种基于人体姿态估计简化版和运动能量结合的方法。由于直接部署完整姿态估计模型如OpenPose负担重我们做了简化边界框交互分析计算每两个人边界框的中心点距离和IoU交并比。如果两个框距离突然变得很近低于阈值T1且IoU大于一个很小的值说明有重叠不是仅仅靠近则标记为“潜在接触”。运动剧烈度分析对于“潜在接触”的成对人跟踪他们边界框中心点在连续帧如5帧内的位移量。如果位移量都很大且方向多变说明肢体动作剧烈。持续时间判断上述“潜在接触”“剧烈运动”的状态持续超过N帧如1秒对应30帧则判定为打架斗殴事件。class FightDetector: def __init__(self, distance_thresh50, iou_thresh0.1, violent_move_thresh30, duration_frames30): self.distance_thresh distance_thresh self.iou_thresh iou_thresh self.violent_move_thresh violent_move_thresh self.duration_frames duration_frames self.potential_fight_pairs {} # 记录每对潜在打架者的持续帧数 def calculate_iou(self, box1, box2): # 计算两个边界框的IoU pass def analyze(self, current_persons, previous_positions): alerts [] current_centers [((box[0]box[2])/2, (box[1]box[3])/2) for box in current_persons] for i in range(len(current_persons)): for j in range(i1, len(current_persons)): dist ((current_centers[i][0]-current_centers[j][0])**2 (current_centers[i][1]-current_centers[j][1])**2)**0.5 iou self.calculate_iou(current_persons[i], current_persons[j]) if dist self.distance_thresh and iou self.iou_thresh: pair_key tuple(sorted((i,j))) # 检查运动剧烈度 (这里需要previous_positions历史轨迹) if self.is_violent_movement(i, j, previous_positions): self.potential_fight_pairs[pair_key] self.potential_fight_pairs.get(pair_key, 0) 1 if self.potential_fight_pairs[pair_key] self.duration_frames: alerts.append((fight, pair_key, current_centers[i])) else: self.potential_fight_pairs.pop(pair_key, None) else: self.potential_fight_pairs.pop(pair_key, None) return alerts4.2.2 区域入侵检测这个相对简单但非常实用。利用OpenCV的cv2.pointPolygonTest函数。在初始化时用一组点定义多边形ROI禁止区域。对于每一帧检测到的每个人体边界框我们取其底部中心点近似人的脚部位置作为判断点。如果该点位于多边形内部则触发区域入侵报警。import cv2 import numpy as np class IntrusionDetector: def __init__(self, polygon_points): # polygon_points: 一个包含(x,y)坐标的列表按顺序定义多边形 self.roi_polygon np.array(polygon_points, np.int32) def analyze(self, person_results): alerts [] for person in person_results: bbox person[bbox] foot_point (int((bbox[0]bbox[2])/2), int(bbox[3])) # 底部中心点 # 判断点是否在多边形内 result 0 表示在内部或边缘 if cv2.pointPolygonTest(self.roi_polygon, foot_point, False) 0: alerts.append((intrusion, foot_point)) return alerts4.2.3 人群聚集检测我们采用人群密度估计的简化方法。在画面中定义多个关注区域如校门口广场计算每个区域内的人数。对每一帧统计落在该区域边界框内的人数。如果人数超过预设阈值如10人且该状态持续数秒避免瞬时波动误报则触发聚集报警。更高级的做法可以计算人群的密度图但对我们这个场景基于框的统计已足够有效。4.3 预警与可视化模块当行为分析模块产生警报事件后预警模块需要做两件事现场可视化立即在监控画面上用醒目的方式标出。例如打架用红色闪烁框入侵用黄色框并填充半透明红色聚集则在区域上方显示红色人数计数。我们使用OpenCV的绘图函数cv2.rectangle,cv2.putText,cv2.polylines实现并利用cv2.addWeighted实现半透明效果。远程通知将警报信息事件类型、时间、摄像头位置、截图通过HTTP POST请求发送到我们搭建的一个简易后台管理平台。平台可以展示警报列表并播放警报声音。我们也尝试了集成钉钉/企业微信的Webhook机器人实现手机端的即时消息推送这对保安人员非常有用。5. 工程部署、优化与踩坑实录5.1 从开发到部署的挑战在本地笔记本上跑通流程只是第一步要让系统7x24小时稳定运行在服务器或边缘设备上会遇到一系列新问题。视频流稳定性校园监控摄像头通常通过RTSP协议传输。网络波动、摄像头重启都会导致cv2.VideoCapture读取失败。我们必须增加重连机制。当cap.read()返回False或长时间没有新帧时需要释放旧的cap对象等待几秒后重新创建连接。资源管理与内存泄漏最初的程序跑几天后内存就耗尽了。原因是OpenCV的窗口、Tensor的缓存没有及时释放。我们做了以下优化在无头服务器没有图形界面上运行时禁用cv2.imshow。使用with torch.no_grad()包装推理代码禁用梯度计算减少内存占用。定期如每处理1000帧使用torch.cuda.empty_cache()清理GPU缓存如果使用GPU。性能瓶颈分析使用Python的cProfile模块或简单的time.time()打点我们发现主要耗时在两部分模型推理和视频解码。对于多路摄像头需要采用多进程或异步IO来处理避免因为一路流的阻塞影响其他路。5.2 模型加速与优化技巧为了在资源有限的设备上部署我们对YOLOv5s模型进行了优化模型导出为ONNX使用YOLOv5自带的export.py脚本将PyTorch模型导出为ONNX格式。ONNX模型具有更好的跨平台性并且可以利用ONNX Runtime进行推理有时比原生PyTorch更快。python export.py --weights runs/train/campus_person_det/weights/best.pt --include onnx --img 640 --dynamic模型量化采用PyTorch的量化API将模型权重从FP32转换为INT8。量化后模型体积减小约4倍推理速度提升1.5-2倍精度损失在可接受范围内mAP下降约1-2个百分点。这是边缘部署的关键步骤。TensorRT部署进阶在NVIDIA Jetson等边缘设备上我们将ONNX模型进一步转换为TensorRT引擎获得了最大的性能提升。这个过程稍复杂需要安装TensorRT并使用其工具进行转换和优化。5.3 常见问题与排查记录在实际运行中我们遇到了不少问题这里记录几个典型的问题一夜间或低光照下检测效果急剧下降。现象白天mAP能达到85%晚上却不到50%很多行人检测不到。排查检查输入模型的图像发现夜间画面噪点多、亮度低、对比度差。解决我们在图像预处理阶段增加了图像增强步骤。使用OpenCV的cv2.createCLAHE对比度受限的自适应直方图均衡化来提升对比度尝试了轻量级的去噪算法如cv2.fastNlMeansDenoisingColored。更根本的解决方案是在数据集中加入大量夜间场景的标注数据重新训练让模型自己学习夜间特征。问题二误报率高特别是树叶晃动、光影变化被误认为人。现象刮风时树下晃动的影子偶尔会触发虚警。排查分析误报帧发现这些“假人”框的置信度通常不高0.3-0.6且宽高比与人体的常见比例不符。解决提高置信度阈值将推理时的conf_thres从0.25提高到0.5过滤掉低置信度的预测。宽高比过滤在postprocess阶段增加一个过滤条件只保留宽高比在一定范围内如0.2到1.0的检测框因为人体框通常是竖长的。轨迹滤波真正的行人框在连续帧间有平滑的运动轨迹。我们实现了一个简单的卡尔曼滤波器或多目标跟踪器如SORT、DeepSORT只有被稳定跟踪了数帧的目标才被认为是有效的“人”瞬间出现的噪声框被滤除。这是降低误报最有效的手段之一。问题三多路视频流处理时CPU利用率100%帧率上不去。现象单路流畅四路同时处理就卡顿。排查Python的GIL限制了多线程并行计算视频解码和模型推理都是计算密集型任务。解决采用多进程架构。我们使用Python的multiprocessing模块为每一路摄像头创建一个独立的进程每个进程负责自己视频流的读取、处理和推理。这样可以利用多核CPU。进程间通过队列multiprocessing.Queue传递警报消息给主进程进行汇总和上报。这样四路视频流可以跑满四个CPU核心帧率大幅提升。问题四模型在特定角度如俯视下检测效果差。现象安装在走廊高处俯拍的摄像头检测到的人框不准漏检也多。原因训练数据集中平视视角的图片占绝大多数模型没有学习到俯视视角下人体的外观特征头大脚小整体更紧凑。解决数据集的视角必须覆盖部署环境。我们补充采集和标注了大量俯视角度的监控画面加入到训练集中进行增量训练fine-tuning让模型适应这种视角变化问题得到显著改善。这个智能校园安全监控系统的项目让我们从理论走向了完整的AI工程实践。从数据采集、模型训练、算法开发到系统集成、性能优化和问题排查走完了一个完整的闭环。最大的体会是一个成功的AI应用算法模型只占一部分更多的挑战在于如何让算法稳定、高效、可靠地在实际环境中跑起来并解决那些书本上不会写的、千奇百怪的 corner case。希望我们踩过的这些坑和总结的经验能为你自己的项目提供一些切实的帮助。本文还有配套的精品资源点击获取