简介:这份资源面向计算机视觉入门与进阶学习者,提供一套基于Python的行人检测完整实现,重点解决视频场景下行人定位与连续跟踪的问题,可服务于智能交通、视频监控等方向的练手与课程实践。压缩包共25个文件,约155.2MB,包含2个py源码文件、2段avi测试视频、11个bmp与5个png行人样本图像,以及4个xml工程配置文件和1个iml模块描述,样本与视频可直接用于特征提取和检测效果验证。目前已有8175人学习下载,具备一定的参考基础。源码围绕HOG特征提取与SVM分类器展开,覆盖灰度化与归一化、多尺度窗口划分、梯度方向直方图构造及块归一化等环节,并给出检测框输出与简单跟踪的衔接思路,读者可据此理解从特征到分类再到跟踪的完整链路,并在此基础上替换样本、调整参数或迁移到其他物体检测任务。
1. 行人检测视频源码包:一份能直接跑起来的计算机视觉入门资源
前阵子帮一个做安防的朋友看项目,他手里有一段园区门口的行人视频,想统计进出人数,又不想从零搭环境。我翻出这份「python行人检测视频+源码」资源包,解压后直接跑通了检测流程,从读视频到画框输出一气呵成。它本质上是一套基于 Python 的行人检测演示工程,核心是调用预训练模型对视频逐帧推理,把行人用矩形框标出来,附带完整可运行的源码和示例视频。适合两类人:一是刚接触计算机视觉、想找一个能跑通的目标检测 demo 建立手感的新手;二是需要快速验证行人检测可行性、再决定是否深入优化的从业者。它不解决高精度追踪和跨镜头重识别,但作为计算机视觉行人检测的起点,省掉了环境配置和模型下载的折腾。
2. 拆开源码包:检测流程与模型选型逻辑
2.1 视频行人检测的完整链路
行人检测看着简单,实际是一条固定链路:视频解码取帧 → 图像预处理 → 模型推理 → 后处理过滤 → 画框写回视频。这份源码把这条链路拆成了几个函数,主循环负责读帧,检测函数负责推理,绘制函数负责标注。理解这条链路比记住某个 API 更重要,因为后面换模型、调阈值、改输入尺寸,动的都是链路上的某个环节。
常见做法是用 OpenCV 的VideoCapture读视频,逐帧转成模型需要的输入格式,推理完再用rectangle画框。源码里对帧率做了保留处理,输出视频的 FPS 和原视频一致,这点对后续做人数统计很关键——帧率错了,统计的时间窗口就全乱了。预处理部分通常包括缩放和归一化,缩放尺寸直接决定检测精度和速度的平衡,源码默认值偏保守,后面会讲怎么调。
2.2 为什么选预训练模型而不是自己训练
这份资源用的是预训练检测模型,没有附带训练脚本。这个选择对入门场景是合理的:行人检测的公开预训练模型已经能覆盖大部分常规视角,自己标注数据训练的成本远高于直接推理。源码里模型加载部分做了本地缓存判断,第一次运行会走下载流程,之后直接读本地权重。
需要说清楚边界:预训练模型的类别里通常包含「人」这一大类,不区分站立、行走、骑行,也不做姿态估计。如果你的场景是密集人群或者遮挡严重,预训练模型的漏检会明显上升,这时候才需要考虑换更重的模型或者做微调。源码包的价值在于把推理链路跑通,让你先看到效果,再判断要不要往深处走。
2.3 环境依赖与首次运行
依赖不多,主要是 OpenCV 和推理框架。建议单独建虚拟环境,避免和系统里其他项目的版本打架。下面是我习惯的初始化步骤:
# 创建并激活虚拟环境,Python 3.8 以上即可 python -m venv ped_env source ped_env/bin/activate # Windows 用 ped_env\Scripts\activate # 安装核心依赖,版本不必锁死,但建议 opencv 用 4.x pip install opencv-python numpy # 如果源码用的是某推理框架,按其 requirements 补齐 pip install -r requirements.txt逻辑说明:虚拟环境隔离是为了防止 OpenCV 版本冲突,这类冲突的典型表现是cv2.imshow报错或者视频写不出去。requirements.txt里如果有版本号,优先按它装,不要盲目升级到最新版,新版 API 变动可能导致源码里某些调用失效。参数上,OpenCV 装opencv-python就够,不需要contrib版本,除非源码里用到了扩展模块。
2.4 跑通第一段视频:命令与参数
源码入口一般是一个主脚本,接受输入视频路径和输出路径两个参数。运行方式大致如下:
# 基本运行:指定输入视频,输出默认写到当前目录 python detect.py --input demo.mp4 --output result.mp4 # 调整置信度阈值和输入尺寸,平衡漏检与速度 python detect.py --input demo.mp4 --output result.mp4 --conf 0.4 --size 640逻辑说明:--conf是置信度阈值,低于它的检测框会被丢弃,调高减少误检但增加漏检,调低反之;--size是推理输入边长,越大精度越高、速度越慢。我一般先用默认值跑一遍看整体效果,再针对具体视频调这两个参数。如果源码没有暴露这些参数,就去主脚本里找对应的变量名,通常在文件头部集中定义,改起来不费事。跑通后先看输出视频有没有正常生成、框有没有画在行人身上,这是判断环境是否正常的第一个信号。
3. 参数调优与效果验证:让检测框稳下来
3.1 置信度与 NMS 阈值的配合
检测框抖动、同一个行人出现多个重叠框,是这类 demo 最常见的观感问题。根源在后处理:置信度阈值决定哪些框留下,非极大值抑制(NMS)阈值决定重叠框怎么合并。两个参数要配合调,单独调一个往往按下葫芦浮起瓢。
我的经验是先固定 NMS 阈值在 0.45 左右,再扫置信度。置信度从 0.5 往下降,观察漏检是否减少、误检是否可接受;如果同一个行人身上出现两三个框,说明 NMS 阈值偏高,适当降到 0.3 到 0.4 之间。源码里这两个值通常是硬编码的,找到后改成命令行参数或者配置文件读取,方便反复试。下面是一个把后处理参数抽出来的写法参考:
# 后处理:先按置信度过滤,再做 NMS 合并重叠框 def postprocess(boxes, scores, conf_thres=0.4, nms_thres=0.45): keep = scores > conf_thres # 置信度过滤,低于阈值的框直接丢 boxes, scores = boxes[keep], scores[keep] indices = nms(boxes, scores, nms_thres) # 合并重叠框 return boxes[indices], scores[indices]逻辑说明:conf_thres控制召回与误检的平衡,nms_thres控制重叠框的合并力度。参数没有万能值,和视频分辨率、行人密度强相关。密集场景下 NMS 阈值要调低,否则相邻行人会被误合并成一个框;稀疏场景可以适当调高,减少框的抖动。
3.2 输入尺寸对速度与精度的影响
输入尺寸是另一个关键旋钮。源码默认尺寸往往偏小,跑得快但小目标行人容易漏。把尺寸调大,远处行人的检测率会明显提升,代价是帧处理时间上升。我一般按视频分辨率来定:720p 的视频用 640 输入基本够用,1080p 且行人较远时考虑 800 或 960。
验证方法很直接:截取视频里行人最远、最小的那一帧,单独跑检测,看框能不能稳定出现。如果远处行人时有时无,就是输入尺寸不够或者置信度阈值偏高。这里有个容易忽略的点——缩放方式。直接拉伸会改变行人宽高比,影响检测效果,常见做法是保持比例缩放后做填充。源码如果用的是直接 resize,可以改成 letterbox 方式,效果会有肉眼可见的提升。
3.3 用固定片段做回归验证
调参最怕改了一个参数、效果好了,改另一个又退回去,最后不知道哪个组合最优。我的习惯是截取一段 10 到 20 秒的固定片段,包含远中近三种距离的行人,每次调参都跑这段,人工数一下漏检和误检数量,记在表格里。
| 参数组合 | 置信度 | NMS | 输入尺寸 | 漏检数 | 误检数 |
|---|---|---|---|---|---|
| 默认 | 0.5 | 0.45 | 416 | 偏多 | 少 |
| 组合 A | 0.4 | 0.4 | 640 | 中等 | 中等 |
| 组合 B | 0.35 | 0.35 | 800 | 少 | 偏多 |
这张表不用追求精确,目的是让调参有据可依,而不是凭感觉来回改。跑完几轮后,选一个漏检和误检都能接受的组合固定下来,再拿完整视频验证一遍。固定片段验证的好处是可复现,换台机器、换个时间跑,结论一致。
4. 避坑与排查:五个真实翻车点
4.1 输出视频打不开或只有几帧
现象:脚本跑完没报错,但输出视频用播放器打开是黑屏,或者只有开头几帧。原因通常是写视频时的编码器或帧尺寸不匹配,OpenCV 的VideoWriter对编码格式和尺寸很挑剔,宽高必须是偶数,编码器要和文件后缀对应。解决:检查VideoWriter的 fourcc 设置,.mp4用mp4v,尺寸从原视频读取后确保是偶数,必要时做一次裁剪。另外确认写循环里write调用在检测之后,别把空帧写进去。
4.2 第一次运行卡在模型下载
现象:运行后长时间无输出,终端停在下载进度。原因是预训练权重默认从网络拉取,网络不稳就会卡住。解决:看源码里权重路径的变量,手动把权重文件放到对应目录,或者改成绝对路径。如果源码没有提供权重下载地址,就找同类模型的公开权重替换,注意输入尺寸和预处理要和权重匹配,否则检测结果会离谱。
4.3 检测框整体偏移
现象:框画出来了,但位置和行人对不上,整体偏上或偏左。原因是预处理时的缩放和填充没有在绘制阶段还原,坐标还停留在模型输入尺度上。解决:找到坐标映射的代码,确认缩放比例和填充偏移都参与了还原。常见错误是只除了缩放比例、忘了减填充偏移,这种偏移在图像边缘最明显。
4.4 CPU 上跑得慢到无法接受
现象:每帧处理好几秒,视频跑完要几个小时。原因是模型默认在 CPU 上推理,且输入尺寸偏大。解决:先降输入尺寸到 416 或 320 看速度是否可接受,再考虑换轻量模型。如果机器有独立显卡,确认推理框架是否装了对应版本,很多框架默认装的是 CPU 版,需要单独装 GPU 版。这一步翻车的人不少,装完以为能用显卡,实际还在跑 CPU。
4.5 换视频后效果断崖式下降
现象:demo 视频效果不错,换成自己的监控视频后漏检严重。原因是预训练模型的训练数据视角和你的视频差异大,俯视角、逆光、夜间都是典型难点。解决:先确认视频本身亮度正常,必要时做预处理增强;再调低置信度阈值看漏检是否改善;如果仍不行,说明模型和场景不匹配,这时候要么换模型,要么考虑用自己场景的数据做微调,源码包本身不覆盖这一步。
5. 从 demo 到可用:加一个简单的越线计数
跑通检测只是起点,真正有用的是在检测基础上做业务逻辑。拿园区门口场景举例,最常见的需求是统计进出人数,实现方式是在画面里画一条虚拟线,记录检测框中心点跨越线的方向。这个逻辑不复杂,但有几个细节决定成败。
先定义线的位置和方向。假设线是水平的,中心点从上往下跨记为进入,从下往上记为离开。每个行人需要一个稳定的 ID 才能判断跨越,简单做法是用检测框中心点的最近邻匹配做简易跟踪,不追求精度,够用就行。下面是一个计数逻辑的骨架:
# 简易越线计数:按中心点纵坐标与虚拟线比较,配合最近邻匹配维持 ID tracked = {} # id -> 上一次的中心点 count_in, count_out = 0, 0 line_y = frame_height // 2 # 虚拟线位置,按场景调整 for det in detections: cx, cy = center_of(det) matched_id = match_nearest(tracked, (cx, cy)) # 最近邻匹配,阈值内视为同一人 if matched_id is not None: prev_y = tracked[matched_id][1] if prev_y < line_y <= cy: count_in += 1 # 从上往下跨线 elif prev_y > line_y >= cy: count_out += 1 # 从下往上跨线 tracked[matched_id or new_id()] = (cx, cy)逻辑说明:line_y是虚拟线的纵坐标,按实际画面调整,放在行人必经的位置;match_nearest用距离阈值判断是不是同一个人,阈值太小会导致 ID 频繁切换、重复计数,太大则会把相邻行人混为一人。这个骨架的局限很明显:行人并排走或者交叉时,最近邻匹配会出错,计数偏差随之而来。要做得稳,得换更正规的跟踪算法,但那已经超出这份源码包的范围了。
验证计数是否靠谱,我的办法是拿一段已知人数的视频跑一遍,人工数实际进出数,和程序结果对比。偏差在可接受范围内再上真实场景。这里有个血泪经验:虚拟线别放在画面边缘,行人刚进画面时检测框还不稳定,容易误触发计数;放在画面中段、行人完整可见的位置,结果会稳很多。
从那以后我每次拿到这类检测源码包,都先跑固定片段、记参数表、再上业务逻辑,三步走完才敢往真实视频上套。希望帮到你。
本文还有配套的精品资源,点击获取