ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于Python的行人识别系统:YOLOv8检测与模型优化实战

基于Python的行人识别系统:YOLOv8检测与模型优化实战 简介这是一份基于Python的行人识别系统本科毕业论文Word文档面向计算机视觉、智能交通与安防监控方向的毕设学生及相关开发者。全篇围绕行人检测、特征提取、跟踪算法、数据集与评价指标展开并给出系统设计与实验分析包含从第一章概述到第六章总结与展望的完整目录结构可直接用于论文选题参考、框架搭建和降重比对。文档共1个docx文件压缩包整体约35KB内容凝练。目前已有311人学习下载。文中不仅梳理了HOG、YOLO、Faster R-CNN、DeepSORT等主流方法还结合Python、OpenCV、PyTorch等工具说明了数据预处理、特征提取、分类器训练和结果分析等实现细节能帮助读者快速把握行人识别系统的研究脉络与写作要点。1. 基于Python的行人识别系统先分清检测和重识别行人识别系统这个标题正式开工前先得拍死一个歧义这里讲的是行人检测detection把画面里每个人用矩形框出来而不是行人重识别ReID判断两个摄像头里出现的是不是同一个人。从“设计与实现”的定位看绝大多数毕业设计和早期企业原型默认前者。用Python落地的理由很直接从OpenCV到ultralyticsPython生态把模型加载、视频流接入、结果可视化整条链路压进了不到一百行代码而真正费劲的推理加速和参数调优又只能在Python脚本里反复试错才能完成。这篇文章按不依赖某个特定开源项目、用现有预训练模型就能跑通的方案来讲适合正在做课程设计、准备技术面试、以及想快速搭一个行人检测原型的开发者。内容锁定在“检测”这个主线上末端补上跨帧追踪和指标验证。2. 行人识别系统的模型选型与数据集准备2.1 检测主干选YOLOv8理由不是“快”这么简单行人检测的模型选型常见的有三条路传统HOGSVM、两阶段Faster R-CNN、单阶段YOLO系列。HOGSVM在2010年前后是主流用方向梯度直方图描述人体轮廓配合线性SVM做分类在密集人群场景下漏检率很高且对遮挡、姿态变化不鲁棒现在只适合在没有GPU加速的最小化部署里兜底。Faster R-CNN先由RPN生成候选区域再做分类回归精度上限高但推理速度通常只有几FPS不符合实时安防场景的基本需求。YOLO系列走到YOLOv8检测头从anchor-based改为anchor-free分类和回归分支解耦在COCO数据集上同等算力下的mAP和FPS都优于同期的稳定版本。对于行人识别系统来说YOLOv8还带了两个实际收益一是内置了person类COCO的class 0预训练权重可以直接复用来检测行人而无需重训二是ultralytics的Python接口把加载模型、推理、画框全部封装好代码量被压缩到最低。很多人纠结YOLOv5和YOLOv8的差异从结果看同等输入分辨率下YOLOv8s在行人这类中小尺度目标上的边界框回归更干净尤其对遮挡目标的处理更稳。提示如果目标场景只有“人”这一类先用官方预训练权重跑通不要一上来就重新训练。重训需要准备至少几千张标注图且效果未必比微调预训练模型好。2.2 数据集选择COCO够用但人群密度高的场景要换用预训练权重做推理时模型已经在COCO train2017的约11.8万张图上训练过覆盖了street、indoor等常见行人场景。直接用它跑通用监控画面准确率足够完成原型演示。但如果真实场景是地铁闸机、商场出入口这类高密度人群COCO里单张图包含几十人的样本比例偏低模型在拥挤场景容易漏检。这时把预训练权重放到CrowdHuman约2.4万人、密集标注上做微调是业界常见做法。在数据集规模这一项上给一个参考对照数据集标注人数规模场景覆盖推荐用途COCO train2017约25万实例80类通用直接推理、多类检测CrowdHuman约47万框密集人群微调后用于高密度场景自建数据集取决于标注量特定机位视角迁移学习时的目标域数据自建数据集的标注格式如果走ultralytics训练流程用YOLO格式最省事每张图片对应一个同名txt文件每一行是class x_center y_center width height四个坐标值都归一化到0到1之间。标注工具用LabelImg或Label Studio导出YOLO格式即可。2.2.1 数据标注里的一个高频错误很多人第一版标注会把人的身体裁剪得特别紧导致框里只有躯干没有头发和脚。YOLO的坐标是中心点加宽高训练时负责匹配的anchor会参考整体宽高比。行人属于典型的高宽比大于1的目标如果标注框的高宽比和大多数样本不一致模型对尺寸的先验就被污染了。标注时框体应该从头顶到鞋底、从身体最左到最右留出1%到2%的边距。2.3 迁移学习只训练最后几层就能适配新场景如果你只有几百张自采图片不要从零开始训练而是用预训练权重做迁移学习。常见的做法是冻结backbone的前十层只训练检测头的参数也可以更激进一点直接解冻全部层用小学习率微调。yolo detect train dataperson.yaml modelyolov8s.pt epochs50 lr00.001 freeze10freeze10表示冻结前10层让早期特征提取层保持COCO的通用特征只调整高层语义和回归头。lr0是初始学习率迁移学习场景下通常设为0.001到0.0001之间比从头训练低一个数量级防止破坏预训练权重。epochs50是一个比较稳的起步值如果验证集的mAP在最后10个epoch仍在上升就翻倍继续训练。训练完成后权重文件会输出到runs/detect/train目录下推理时把model参数指向这个权重文件即可。3. Python环境下行人识别系统的核心实现3.1 最小可运行的推理脚本把模型跑起来ultralytics是当前最顺手的入口。安装只依赖一个PyTorch环境pip安装即可pip install ultralytics opencv-python下面的代码从摄像头或图片读取并输出检测框from ultralytics import YOLO # 加载预训练权重yolov8n是轻量版yolov8s是平衡版 model YOLO(yolov8s.pt) # 用摄像头作为输入源时source传入设备索引 results model.predict( source0, # 0表示第一个摄像头 conf0.35, # 置信度阈值低于此值的预测会被丢弃 iou0.5, # NMS的IoU阈值值越小抑制越强 classes[0], # 只保留COCO中的person类索引0 saveTrue, # 将标注后的画面保存到runs/detect目录 verboseFalse # 不打印逐帧日志 )这段代码的关键在classes[0]这个参数。COCO数据集里person类的索引是0加上这个过滤之后模型只输出行人检测框不会把车、椅子、动物等目标也画出来。如果没有这一步输出画面会混杂大量非行人框对后面的计数和追踪逻辑会产生严重干扰。conf和iou是两个直接影响系统表现的参数conf设低召回高但误检多conf设高结果干净但可能放过遮挡严重或远距离的小目标。iou则是非极大值抑制的控制参数值越小重叠的框被抑制得越狠同一目标的重复框越少。3.2 视频流检测与结构化结果导出上面的脚本只是把检测结果画在画面上。真实系统还需要把每一帧的行人坐标、置信度输出成结构化数据供后续做计数、轨迹分析或者接入业务系统。import cv2 from ultralytics import YOLO model YOLO(yolov8s.pt) cap cv2.VideoCapture(input.mp4) fps cap.get(cv2.CAP_PROP_FPS) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 输出视频编码器mp4v兼容性最好 writer cv2.VideoWriter( output.mp4, cv2.VideoWriter_fourcc(*mp4v), fps, (width, height) ) while cap.isOpened(): ret, frame cap.read() if not ret: break result model.predict(frame, conf0.35, classes[0])[0] boxes result.boxes # boxes.xyxy是左上右下坐标conf是置信度cls是类别索引 for box in boxes.xyxy.cpu().numpy(): x1, y1, x2, y2 box.astype(int) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) writer.write(frame) cap.release() writer.release()这段代码把检测从单张图片扩展到了完整视频result.boxes.xyxy返回的是每帧所有检测框的坐标格式是左上角(x1, y1)和右下角(x2, y2)如果模型是在GPU上推理的需要先调.cpu()再转 numpy否则后续的OpenCV绘图操作会跟显存张量冲突。循环体里的model.predict每帧调用一次在没有TensorRT加速的情况下单帧耗时约20到40毫秒取决于显卡型号和输入分辨率处理1080p视频基本能跟上游帧率持平。如果需要保存检测结果而非仅保存画面在循环内部把x1, y1, x2, y2, conf写入CSV即可常见的做法是给每一帧带上时间戳便于后续按时间段聚合统计。3.3 抽帧与ROI裁剪让系统更贴合业务实时性不够时有一个零成本的优化不要对每一帧做检测。监控场景下行人移动速度有限每秒检测5到10帧足够满足计数和区域入侵报警需求。frame_interval 5 # 每5帧检测一次 frame_count 0 while cap.isOpened(): ret, frame cap.read() if not ret: break if frame_count % frame_interval 0: result model.predict(frame, conf0.35, classes[0])[0] # 保存检测结果或画框 # ... frame_count 1抽帧的核心逻辑是让模型少算四分之三的帧同时保持输出流稳定。如果下游业务要求每秒都有数据前一次检测的结果可以直接复用到中间被跳过的帧上这种“检测结果保持”的策略在很多商业系统里是默认行为。另一个贴合业务的常见操作是ROI裁剪。摄像头画面里总有永远不可能出现行人的区域比如天空、墙壁、远处的树丛这些区域的纹理复杂容易触发误检。只对预设的矩形区域做检测能显著降低误检率。# 只对画面中的矩形区域做检测减少无关区域的干扰 roi frame[100:500, 200:800] result model.predict(roi, conf0.35, classes[0])[0] # 注意检测框坐标是基于roi的回填到原图时要加上偏移 for box in result.boxes.xyxy.cpu().numpy(): x1, y1, x2, y2 box.astype(int) x1 200 y1 100 x2 200 y2 100ROI裁剪时最容易漏掉的是坐标偏移。很多人直接从result里取框坐标画回原图结果所有框都偏到左上角去了。这是因为predict输入的图本身被裁剪过输出坐标自然基于裁剪后的坐标系。回填偏移量这个步骤是所有做区域检测的人都踩过一遍的坑。4. 行人识别系统的推理加速与参数调优4.1 依赖瓶颈先看数据流水线再看模型遇到识别系统慢的时候第一反应通常是换更大的模型或者上更好的显卡但实际项目里最常见的瓶颈在视频解码和图像缩放。有一个很容易踩的坑cv2.VideoCapture读取高分辨率视频时解码本身会消耗大量CPU。如果摄像头是4K的但检测目标只占画面的一小块先在读取后立刻缩放再送进模型比直接让模型处理4K输入要快得多。ultralytics的predict接口默认会把输入缩放到模型的训练分辨率通常不超过1280像素所以喂给模型的图实际上已经缩放过了省掉的只是解码端的开销图像缩放本身节省的算力非常可观。4.2 三个必调的检测参数YOLOv8的推理参数看似很多真正影响系统质量的只有置信度阈值、NMS的IoU阈值和输入分辨率。给出一份常用的配置参考参数名参数位置建议取值范围调高/调低的影响confpredict的conf0.25到0.5调低召回高但误检多调高更精准但漏检多ioupredict的iou0.4到0.7调低重叠框抑制更强调高更容易保留小目标重复框imgszpredict的imgsz640到1280调高小目标检出率高但显存和耗时上升这里的imgsz值得单独说明它控制模型输入的尺度。检测小目标时直接把imgsz从640提到960或1280效果往往比换更大的模型更明显。一个行人如果只占画面高度的5%在640×640输入里可能只有16个像素高模型很难提取到有效特征放大到1280后同样的目标变成32像素高检出概率显著提升。代价是推理时间翻倍所以要在检测率和实时性之间找平衡。4.3 用ONNX Runtime把模型部署到CPU机器上很多设备要求系统在无GPU的笔记本上也跑得动。PyTorch的推理在CPU上非常慢因为模型存储格式和算子调度没有针对CPU做充分优化。常见的做法是导出为ONNX格式再交给ONNX Runtime的CPU执行引擎yolo export modelyolov8s.pt formatonnx opset12 simplifyTrue导出后用ONNX Runtime加载import cv2 import numpy as np import onnxruntime as ort session ort.InferenceSession(yolov8s.onnx, providers[CPUExecutionProvider]) input_name session.get_inputs()[0].name # 预处理缩放到640x640BGR转RGB再归一化到0~1 img cv2.imread(street.jpg) img_resized cv2.resize(img, (640, 640)) img_rgb cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) blob img_rgb.astype(np.float32) / 255.0 blob np.transpose(blob, (2, 0, 1))[np.newaxis, ...] outputs session.run(None, {input_name: blob})ONNX Runtime的收益在不同机器上不一样。在笔记本CPU上相比原始PyTorch模型通常有1.5到2倍的加速如果机器支持还可以把providers设置为[CUDAExecutionProvider, CPUExecutionProvider]由CUDA优先执行。要注意的是ONNX导出时标注的opset版本需要与推理端兼容opset 12是兼容性最好的中间值。4.4 多路视频流的处理进程隔离比线程更可靠一个行人识别系统对接几路摄像头很常见。Python的多线程受GIL限制推理任务在多核CPU上无法线性扩展常见的做法是用multiprocessing按摄像头分进程每个进程独立加载模型并处理一路流。from multiprocessing import Process def process_stream(stream_url, device_id): model YOLO(yolov8s.pt) cap cv2.VideoCapture(stream_url) # 每路视频独立循环模型各自持有避免锁竞争 while cap.isOpened(): ret, frame cap.read() if not ret: break result model.predict(frame, conf0.35, classes[0])[0] # 将结果写入共享队列或数据库 if __name__ __main__: streams [rtsp://camera1, rtsp://camera2] processes [Process(targetprocess_stream, args(s, i)) for i, s in enumerate(streams)] for p in processes: p.start()要注意的是GPU显存每个进程都会加载一份模型权重在显存有限的情况下要么减小imgsz要么在进程内用torch.cuda.set_per_process_memory_fraction限制显存使用。CPU模式下则要考虑内存占用yolov8s的权重约22MB四路视频大约需要多占不到100MB可以接受。5. 从检测到追踪行人识别系统的落地验证技巧5.1 用最简IOU匹配实现跨帧追踪检测模型给出的每一帧框都是独立的同一个行人在连续帧里没有ID关联。要做人数统计、行进轨迹或者越界报警必须在相邻帧之间做目标匹配。不引入DeepSORT这类重识别模型的情况下最简单的做法是IOU匹配下一帧的框和上一帧已有轨迹的框计算交并比超过阈值就认为是同一个目标。def iou(box1, box2): x1 max(box1[0], box2[0]) y1 max(box1[1], box2[1]) x2 min(box1[2], box2[2]) y2 min(box1[3], box2[3]) inter_area max(0, x2 - x1) * max(0, y2 - y1) box1_area (box1[2] - box1[0]) * (box1[3] - box1[1]) box2_area (box2[2] - box2[0]) * (box2[3] - box2[1]) union_area box1_area box2_area - inter_area return inter_area / union_area if union_area 0 else 0阈值一般设0.3低于这个值的矩形框视为新出现的目标。行人步速下前后两帧的框重叠率通常高于0.50.3留出了镜头抖动和检测框抖动的余量。用这个IOU匹配做接力就能得到一个不依赖第三方库的轻量追踪器要追求更高精度再换成ByteTrack。5.2 验证系统效果的三个数字验收行人识别系统不只看画面效果更重要的是mAP、FPS和漏检率。mAP的计算需要标注好的验证集ultralytics提供了内置的验证命令yolo detect val modelyolov8s.pt dataperson.yamldataperson.yaml指向的YAML文件要声明验证集图片路径和类别名称。验证完成后会输出mAP50和mAP50-95对行人检测来说mAP50是主要参考0.8以上算及格线。FPS的数字要区分“模型推理FPS”和“端到端FPS”后者包含解码、预处理、后处理、画框全流程在方案汇报时应以端到端为准。建议把置信度阈值、IOU阈值、输入分辨率三个参数做成配置项单独抽到一个配置文件里。因为换数据集或换摄像头后这三组参数几乎一定要重新调整而这套配置能帮你把整个调参过程收敛在一个文件里避免每次都去改推理脚本中的魔法数字。本文还有配套的精品资源点击获取
返回列表