
简介一份面向计算机视觉入门与进阶学习者的行人检测实战项目基于Python与OpenCV实现HOG特征提取与SVM分类器并结合简单跟踪算法完成视频流中的行人检测与持续跟踪。资源包共25个文件压缩包大小约155.2MB包含2个Python源码main.py与detection1.py、11个bmp与5个png图像样本、4个xml模型或配置、2个avi测试视频及1个IDE工程文件图像样本用于模型训练与测试xml文件保存分类器参数avi视频作为检测输入py脚本承载完整流程目录结构便于直接运行、调试与二次开发。已有8170人学习下载适用于智能交通、视频监控、安全防护等场景的课程设计或技术调研。内容覆盖HOG特征计算流程、SVM二分类原理、多尺度滑窗检测以及基于预测与校正的简单跟踪思路配合多样图像样本与真实视频演示可帮助读者从零搭建并理解一个完整的行人检测系统进而迁移到其他目标检测任务中。 最近有个业余项目要把一段商场监控录像里的行人自动检测出来并且生成带标注框的输出视频。我顺手把这套流程整理成了可复用的Python源码核心逻辑不复杂读取视频帧、用目标检测模型识别行人、画框标注、再写回视频文件。今天就把完整思路和源码拆开讲清楚项目用到的技术栈是PythonOpenCVYOLOv8适合刚接触计算机视觉、想用现成模型做视频分析的开发者参考。这类需求在实际场景里特别常见——客流统计、安防监控、自动驾驶辅助、商业区域热力分析底层都离不开“视频里找人”这一步。难点不在单帧检测而在怎么把模型高效地接进视频流处理流程里保证帧率、稳定性和输出质量。文章会从方案选型、环境配置、模型选择、核心代码实现、性能优化到常见问题一步步把坑都填平。1. 需求拆解与技术路线选型1.1 先想清楚视频行人检测到底要解决什么问题视频行人检测的本质就是把“视频”拆成“帧”在每一帧图像里定位人的位置输出边界框再把结果叠加到画面上。听起来简单但有几个关键点直接决定方案能不能落地输入是视频文件还是摄像头实时流文件的处理可以逐帧慢慢算实时流就必须考虑推理速度。输出是什么要标注视频、统计人数还是只抽帧检测运行环境有没有GPU这决定了模型大小和推理后端的选择。我这次的需求是离线处理一段MP4监控录像输出带检测框的新视频顺便统计每一帧的行人数量。基于这个明确目标选型思路就清晰了。1.2 为什么我选了YOLOv8而不是传统方案或更早版本目标检测的路线大致有三类传统图像处理、两阶段检测器、单阶段检测器。传统方案比如OpenCV自带的HOG特征SVM行人检测优点是无需深度学习环境、CPU跑得动但缺点太致命——对小目标、遮挡、姿态变化的鲁棒性很差监控画面里人稍微重叠就乱套。只能当学习案例不适合真实项目。两阶段检测器里最具代表性的Faster R-CNN精度确实高但推理速度慢处理视频时每帧要跑几百毫秒。在离线分析场景勉强能用一旦涉及实时监控或者长视频批量处理效率就撑不住了。单阶段检测器里YOLO系列是目前工业落地最广的选择。我选YOLOv8核心原因有三点推理速度快同硬件条件下比YOLOv5更快更稳。使用Ultralytics封装好的API加载模型、推理、后处理全部内置代码量极少。预训练权重基于COCO数据集自带person类别类别ID为0做行人检测开箱即用不需要自己标注训练就可以跑通全流程。如果你更熟悉YOLOv5或YOLOv7思路完全一致后面讲的优化方法也都通用只是API细节有些差异。选型结论以YOLOv8为检测核心OpenCV负责视频读写Python完成流程串联。既保证精度够用又把代码复杂度控制在合理范围。2. 开发环境准备与踩坑2.1 一份能直接跑起来的环境版本清单先列一下我这边的环境版本照着搭基本不会出问题组件版本说明Python3.103.8-3.10均可不建议用3.11部分依赖编译容易踩坑PyTorch2.1.0CPU版或CUDA版根据机器选择ultralytics8.1.xYOLOv8官方封装库opencv-python4.9.0视频读写和图像处理numpy1.26.x科学计算基础库强烈建议用虚拟环境别把依赖直接装到系统Python里不然项目多了依赖冲突会让人崩溃。创建虚拟环境的命令python -m venv pedetect_env source pedetect_env/bin/activate # Windows下用 pedetect_env\Scripts\activate激活后统一安装pip install ultralytics opencv-python numpy这会自动拉取PyTorch和依赖。如果机器有NVIDIA GPU并且想用CUDA加速建议先去PyTorch官网选择对应的安装命令手动安装CUDA版PyTorch再装ultralytics否则默认装的可能是CPU版。2.2 版本兼容最容易被忽视的两个坑第一个坑是CUDA和PyTorch版本不匹配。装完以后一定要验证一下GPU能不能正常调用import torch print(torch.cuda.is_available()) # 输出True才说明GPU可用如果这里输出False大概率是CUDA版PyTorch没装对或者显卡驱动太旧别急着往下写代码先解决环境问题。第二个坑在OpenCV的包名上。安装时用opencv-python但导入时写import cv2。有时候项目里同时装了opencv-contrib-python会和普通版冲突出现奇怪的属性缺失报错。我遇到过cv2.VideoCapture无法打开视频文件的情况最后排查发现是conda和pip混装了两个版本。解决办法是统一用pip重装先卸载再装一个版本。3. 模型与数据准备3.1 直接用官方权重还是自己训练先明确一个观念做行人检测绝大多数情况下不需要从头训练模型。YOLOv8官方提供在COCO数据集上训练好的模型权重COCO的80个类别里就包含personid为0覆盖了行人、自行车、公交车等常见场景。直接加载预训练权重然后用classes[0]参数让模型只输出行人这一类效果足够应付大多数监控、街拍、视频分析需求。YOLOv8提供了几个不同规模的权重核心区别是速度和精度的取舍权重文件参数量特点适用场景yolov8n.pt约320万最轻量速度快精度略低CPU处理、实时预览、长视频批量处理yolov8s.pt约1110万速度和精度的平衡点大多数场景的首选yolov8m.pt约2590万精度更高速度下降有GPU、对精度要求高的场景yolov8l.pt约4360万精度高速度明显下降离线分析、单帧精度优先yolov8x.pt约6820万精度最高几乎只适合GPU集群或离线超精细分析我第一次跑的时候用yolov8n在CPU上检测视频速度还行但画面里稍远一点的行人容易漏检。后面换成yolov8s漏检率降了不少帧率还能接受。如果机器性能一般建议从yolov8s起步不要一上来就用最大模型。3.2 需要提升精度时的数据策略如果官方权重在你的场景里效果不佳——比如画面里行人特别密集、姿态复杂、需要检测特定区域工地、学校门口——那就需要考虑微调模型。但这不是必要的第一步先把官方权重用起来确认流程没问题后再考虑提精度。真要微调推荐用CrowdHuman或者MOT Challenge这些公开行人数据集做增量训练。标注格式建议直接用YOLO格式每张图对应一个txt文件每一行是class x_center y_center width height四个坐标值都是归一化后的比例。标注工具推荐LabelImg或X-AnyLabeling这个坑我在标注阶段踩了不少——标注框尽量贴合人形轮廓把遮挡部分按可见区域框不要追求框住想象中的完整身体否则模型学到的边界是错的。4. 核心代码实现逐段拆解4.1 整体流程设计整个视频行人检测流程可以拆成五个环节初始化加载模型打开视频读取视频参数。读取帧循环从视频中读取一帧图像。推理检测将帧送入模型获得行人的边界框、置信度。绘制标注在帧上绘制矩形框和文字标签。输出写回视频文件同时显示在窗口中。下面是一份可以直接运行的完整代码模块化写在后面方便你根据实际需求裁剪import cv2 from ultralytics import YOLO def load_model(weights_pathyolov8s.pt): return YOLO(weights_path) def process_video(model, input_path, output_path, conf_thres0.45, iou_thres0.45): cap cv2.VideoCapture(input_path) if not cap.isOpened(): raise ValueError(f无法打开视频文件: {input_path}) # 读取视频参数 fps int(cap.get(cv2.CAP_PROP_FPS)) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 初始化视频写入器 fourcc cv2.VideoWriter_fourcc(*mp4v) writer cv2.VideoWriter(output_path, fourcc, fps, (width, height)) frame_idx 0 while cap.isOpened(): ret, frame cap.read() if not ret: break # 推理只检测person类别COCO中id为0 results model(frame, classes[0], confconf_thres, iouiou_thres, verboseFalse) # 绘制检测结果 annotated_frame results[0].plot() # 计算当前帧人数 person_count len(results[0].boxes) cv2.putText(annotated_frame, fPerson Count: {person_count}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2) writer.write(annotated_frame) cv2.imshow(Pedestrian Detection, annotated_frame) if cv2.waitKey(1) 0xFF ord(q): break frame_idx 1 if frame_idx % 30 0: print(f已处理 {frame_idx}/{total_frames} 帧) cap.release() writer.release() cv2.destroyAllWindows() print(f处理完成结果已保存至: {output_path}) if __name__ __main__: model load_model(yolov8s.pt) process_video(model, input.mp4, output.mp4)这段代码里最核心的是results model(frame, classes[0], confconf_thres, iouiou_thres)这一行返回的results对象里封装了检测框坐标、置信度和类别。results[0].plot()直接返回画好框的帧图像省去手动绘制的大量代码。当然你完全可以手动绘制方便自定义颜色和标签for box in results[0].boxes: x1, y1, x2, y2 map(int, box.xyxy[0]) confidence float(box.conf[0]) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fperson {confidence:.2f}, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)box.xyxy[0]的格式是[x1, y1, x2, y2]即左上角和右下角坐标。手动绘制的好处是可以在框上叠加更多业务信息比如行人编号、轨迹、区域判定结果。4.2 关键参数调优conf、iou、imgsz各自的角色模型推理时有几个参数对效果影响很大很多人只知道调但不理解为什么。conf置信度阈值决定多“自信”的检测结果才会被保留。阈值设低比如0.25检出的框多但误检也多阈值设高比如0.7误检少但漏检增加。监控画面里行人通常比较清晰我习惯设在0.45-0.55之间。如果画面模糊、有雾或者夜间红外模式适当降到0.3以下否则人会被漏掉。iouNMS交并比阈值作用于非极大值抑制解决同一个行人产生多个重叠框的问题。NMS的过程是模型会生成大量候选框其中同一目标周围可能有多个iou阈值决定哪些重叠框被合并。阈值设低比如0.3抑制力度强密集人群容易误杀相邻人的框阈值设高比如0.7抑制力度弱同一个目标可能出现重复框。行人检测场景0.45是最常用的默认值实测覆盖了大多数情况。imgsz是推理时的输入尺寸。YOLOv8默认把输入图像缩放到640x640然后进行推理。增大到1280能检测更小的行人但推理时间显著增加减小到416能提速但小目标漏检率上升。处理1080p视频时我建议先用默认640跑一遍看效果如果远处小目标漏检明显再单独对高分辨率关键帧做一次1280推理做多尺度融合。参数取值范围作用推荐设置conf0.1-0.7控制误检与漏检的平衡0.45iou0.3-0.7抑制同目标重复框0.45imgsz416-1280输入分辨率影响小目标检测640起步classes类别ID列表过滤检测类别[0]只看person4.3 输出部分要注意的编码问题写视频文件时最常见的坑就是输出文件打不开或者没有声音。没有声音是正常的——这个流程只处理画面原始音频不会保留。但文件打不开多半是编码器选错了。fourcc cv2.VideoWriter_fourcc(*mp4v) writer cv2.VideoWriter(output_path, fourcc, fps, (width, height))常见编码器对比fourcc输出格式兼容性说明mp4v.mp4通用兼容性最好推荐首选avc1.mp4部分播放器可播H.264编码体积小但OpenCV支持看环境XVID.avi通用老格式文件体积大H264.mp4依赖ffmpeg需要OpenCV编译时支持ffmpeg注意VideoWriter必须使用和输入视频相同的(width, height)和fps否则写出的视频要么变形、要么时长对不上。我遇到过一次输入是1920x1080读取时width和height属性竟然拿到的是0排查后发现是视频文件本身损坏OpenCV读不到元信息换个源文件就好了。5. 性能优化与实测结果5.1 我的实测数据CPU和GPU差多少为了让你对性能有直观概念放一组我机器上的实测数据。视频源是一段1080p、30fps、时长2分钟的商场监控录像测试机配置为i7-10750H GTX 1660 Ti。权重硬件推理耗时/帧处理全片总耗时说明yolov8nCPU约75ms约4.5分钟勉强实时偶有漏检yolov8sCPU约150ms约9分钟效果OK速度很慢yolov8nGPU约18ms约1.1分钟实时流畅yolov8sGPU约28ms约1.7分钟推荐组合精速度和精度兼顾实测下来的结论如果只是离线处理一段几分钟的视频CPU加上yolov8n也可以接受只是需要等但你要是处理摄像头实时流或者批量处理几十段视频没有GPU真的会怀疑人生。5.2 还能再快的三招推理后端、跳帧跟踪、多线程读取第一招换推理后端。Ultralytics支持将模型导出为ONNX、OpenVINO、TensorRT等格式。OpenVINO在Intel CPU上能比原生PyTorch快两到三倍TensorRT在NVIDIA GPU上能再压榨一截性能。model YOLO(yolov8s.pt) model.export(formatopenvino) # 导出OpenVINO格式 ov_model YOLO(yolov8s_openvino_model)导出后再加载就是优化后的模型代码完全不需要改。第二招跳帧加跟踪。这是解决长视频效率问题的“作弊”手段不是每一帧都做检测而是每隔N帧检测一次中间的帧用跟踪算法如ByteTrackUltralytics内置预测目标位置。行人短时间内的位移是连续的跳3-5帧通常问题不大。实测1080p视频跳3帧处理速度接近原来的3倍检测效果肉眼几乎看不出差别。results model.track(frame, classes[0], persistTrue, trackerbytetrack.yaml)第三招多线程预读取。视频解码IO和模型推理是两块不同耗时用生产者-消费者模式一个线程专门读帧一个线程专门推理能藏掉视频读取的延迟。尤其处理高码率视频时效果明显。这一招适合进阶优化新手上手先把前两个做了就够用。6. 常见问题与排查技巧6.1 典型问题速查表现象可能原因解决办法cap.isOpened()返回False视频路径错误、编码不支持、文件损坏用potplayer或ffmpeg验证视频能否打开换一段标准h264编码的视频测试检测框画不出来conf阈值太高、模型没正确加载降到0.2试试打印results查看是否有输出确认模型文件存在GPU利用率一直是0%装成了CPU版PyTorch验证torch.cuda.is_available()重新安装CUDA版PyTorch输出视频文件0字节VideoWriter初始化失败检查fourcc是否支持mp4v确认输出目录可写检查width/height是否正常读取推理速度极慢视频分辨率过高、CPU推理大模型先缩放帧到1280以内降级到yolov8n导出OpenVINO画面检测框抖动厉害单帧独立检测没有时序约束使用model.track()开启跟踪适当降低fps输出平滑显示6.2 两个容易被忽略的坑第一个坑视频打不开不一定是代码问题。有一次我拿到一段从网上下载的FLV视频OpenCV怎么都打不开但PotPlayer放得好好的。原因是视频实际编码是H.265HEVCOpenCV原生对H.265支持很差。解决办法是用ffmpeg转码成H.264的MP4ffmpeg -i input.flv -c:v libx264 -crf 23 output.mp4以后再遇到打不开的视频先看编码格式别一上来就改代码。第二个坑检测框闪烁不定。单帧独立检测时同一行人在相邻帧的置信度会有波动导致某几帧突然消失或框突然变大变小。这在高清监控里特别明显。用跟踪模型配合persist参数可以显著提升稳定性——我的经验是凡是做视频输出尽量用model.track()而不是model()哪怕不做跳帧画面稳定性提升都很明显。我个人在实际操作中的体会是视频行人检测这个项目最关键的瓶颈不是“检测”本身而是“视频工程化”。模型选择、参数调优只要理解原理就能快速定位反而是在视频解码、编码器、帧率一致性、线程调度这些非AI环节暗坑更多。刚开始学的时候不要贪多先跑通最简单的版本拿到可用的输出视频再一步步加入跟踪、优化、统计这样排错效率最高。做完基础检测之后你可以继续扩展的方向很多行人计数并生成随时间变化的人数曲线、划定电子围栏实现区域入侵报警、结合多目标跟踪输出行人轨迹热力图甚至可以接上MQTT把检测结果实时上报到Web端。每一块都是独立成篇的技术点。代码全都可以基于这套流程改出来祝顺利。本文还有配套的精品资源点击获取