第一次接触视频动作识别任务时,我像大多数开发者一样被各种开源框架弄得眼花缭乱。经过几轮对比测试,最终选择了MMAction2,原因很简单——它就像视频分析领域的瑞士军刀。这个基于PyTorch的开源工具包不仅支持行为识别、时序动作定位等五大核心任务,更重要的是它的模块化设计让二次开发变得异常轻松。
记得当时测试过一个篮球动作识别项目,需要同时处理实时视频流和预录制的比赛录像。MMAction2提供的统一接口让我用同一套代码就搞定了两种输入源的适配,这在其他框架中往往需要大量定制代码。官方文档中那个"5分钟快速上手"的demo没有骗人,我确实在短时间内就跑通了第一个识别模型。
新手最容易栽跟头的就是环境配置。官方推荐用pip直接安装,但实测下来在Ubuntu 20.04上会遇到MMCV版本冲突的经典问题。我的建议是直接使用Docker——这不是偷懒,而是真的能省下至少半天排错时间。
在docker目录下执行build命令时,90%的人会遇到GPG签名错误。这个坑我踩过三次,解决方案是在Dockerfile里添加密钥服务器配置:
dockerfile复制RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3B4FE6ACC0B21F32
记得把末尾的密钥替换成你实际报错的编码。这个步骤要放在apt-get update之前,否则缓存问题会导致后续安装全部失败。
MMAction2 1.x和0.x版本就像两个不同的世界。有次我照着旧教程装新版本,死活调不通帧图推理功能,后来才发现--use-frames参数只在0.24.1等旧版中存在。建议新手这样选择:
先看最基础的视频推理命令:
bash复制python demo/demo.py \
tsn_imagenet-pretrained-r50_8xb32-1x1x8-100e_kinetics400-rgb.py \
tsn_imagenet-pretrained-r50_8xb32-1x1x8-100e_kinetics400-rgb_20220906-2692d16c.pth \
demo/demo.mp4 \
tools/data/kinetics/label_map_k400.txt
这里有个隐藏知识点:输入视频的帧率会被自动统一处理。但如果你要处理监控摄像头这种非标准输入,最好先用FFmpeg预处理:
bash复制ffmpeg -i input.mov -r 25 -vf scale=340:256 output.mp4
当项目要求传入Base64编码的帧图时,事情就变得有趣了。旧版MMAction2要求图片命名必须是img_00001.jpg这样的固定格式,但实际项目中我们往往拿到的是随机命名的内存图像。这时需要自己写个预处理脚本:
python复制import cv2
import numpy as np
def frames_to_mmaction_input(frames):
# frames是Base64解码后的图像列表
temp_dir = "temp_frames"
os.makedirs(temp_dir, exist_ok=True)
for i, frame in enumerate(frames):
cv2.imwrite(f"{temp_dir}/img_{i:05d}.jpg", frame)
return temp_dir
记得在推理命令末尾加上--use-frames参数,否则系统会默认按视频处理。这个细节在官方文档里藏得很深,我当初排查了整整一天。
当需要处理大量视频时,直接循环调用demo.py效率极低。我改进后的方案是重写推理逻辑:
python复制from mmaction.apis import inference_recognizer
from mmengine import Config
cfg = Config.fromfile('configs/recognition/tsn/tsn_r50_video.py')
model = init_recognizer(cfg, 'checkpoints/tsn.pth')
def batch_inference(video_paths):
results = []
for path in video_paths:
frames = extract_frames(path) # 自定义抽帧函数
result = inference_recognizer(model, frames)
results.append(top_k(result, 3))
return results
处理长视频时容易爆显存,这时可以启用帧采样策略。在配置文件中修改test_pipeline:
python复制test_pipeline = [
dict(type='SampleFrames', clip_len=32, frame_interval=2, num_clips=1),
# 其他处理步骤...
]
clip_len控制采样帧数,frame_interval设置间隔。对于1分钟以上的视频,建议frame_interval设为3-5,既能保留关键动作又节省资源。
在健身房动作识别项目中,我发现默认的Kinetics-400预训练模型对某些专业动作识别率很低。这时可以尝试以下改进:
python复制model=dict(
cls_head=dict(
num_classes=20, # 改为你的实际类别数
in_channels=2048,
spatial_type='avg',
dropout_ratio=0.5))
python复制train_pipeline = [
dict(type='RandomResizedCrop', scale=(224, 224)),
dict(type='Flip', flip_ratio=0.5),
dict(type='Normalize', **img_norm_cfg),
dict(type='FormatShape', input_format='NCHW'),
dict(type='Collect', keys=['imgs', 'label'], meta_keys=[]),
dict(type='ToTensor', keys=['imgs', 'label'])
]
Flip增强对左右对称动作效果明显,但对游泳这类有方向性的动作反而会造成干扰。
上线后我发现一个诡异现象:夜间低光照视频的识别准确率会断崖式下跌。后来增加了预处理检测模块:
python复制def check_video_quality(frame):
# 计算图像清晰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
fm = cv2.Laplacian(gray, cv2.CV_64F).var()
# 检测光照条件
hist = cv2.calcHist([gray],[0],None,[256],[0,256])
dark_ratio = hist[:50].sum()/hist.sum()
return fm > 20 and dark_ratio < 0.3
对于不合格的视频,自动触发图像增强或直接返回"低质量视频"状态码,比硬着头皮推理效果更好。
在边缘设备部署时,我对比过三种方案:
以Jetson Xavier为例,TensorRT优化后的推理速度能提升3-5倍。关键步骤是:
bash复制# 导出ONNX
python tools/deployment/pytorch2onnx.py \
configs/recognition/tsn/tsn_r50_video.py \
checkpoints/tsn.pth \
--shape 1 3 32 224 224
# TensorRT优化
trtexec --onnx=tsn.onnx \
--saveEngine=tsn.engine \
--fp16 \
--workspace=2048
注意要指定--shape参数匹配实际输入维度,视频模型通常是5维输入(batch, channel, time, height, width)。