利用I3D膨胀三维卷积网络实现视频动作分类
I3D(Inflated 3D ConvNet)是由DeepMind提出的视频理解模型,它将2D卷积核膨胀为3D,并结合光流分支,在Kinetics-400等大规模数据集上取得了突破性性能。本指南介绍如何加载预训练I3D权重并对自定义视频进行分类。
环境准备
本项目依赖TensorFlow和Sonnet,可通过以下命令安装:
pip install tensorflow dm-sonnet
获取模型代码及预训练权重:
git clone https://github.com/deepmind/kinetics-i3d.git
cd kinetics-i3d
模型加载与推理
首先导入必要模块,并构建RGB和光流两支I3D模型:
import tensorflow as tf
import numpy as np
from i3d import InceptionI3d
# 输入规格:RGB (None, 帧数, 224, 224, 3),Flow (None, 帧数, 224, 224, 2)
rgb_input = tf.placeholder(tf.float32, shape=(None, 64, 224, 224, 3))
flow_input = tf.placeholder(tf.float32, shape=(None, 64, 224, 224, 2))
with tf.variable_scope('RGB'):
rgb_model = InceptionI3d(num_classes=400, spatial_squeeze=True, final_endpoint='Logits')
rgb_logits, _ = rgb_model(rgb_input, is_training=False)
with tf.variable_scope('Flow'):
flow_model = InceptionI3d(num_classes=400, spatial_squeeze=True, final_endpoint='Logits')
flow_logits, _ = flow_model(flow_input, is_training=False)
# 恢复预训练参数
rgb_saver = tf.train.Saver(var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='RGB'))
flow_saver = tf.train.Saver(var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='Flow'))
视频预处理与分类函数
使用MediaPipe进行视频帧提取与光流计算。下面实现一个用于处理视频并返回模型输入的辅助方法:
def extract_rgb_and_flow(video_path, num_frames=64, frame_size=224):
"""从视频中抽取固定帧数的RGB张量与光流张量"""
import mediapipe as mp
cap = cv2.VideoCapture(video_path)
frames = []
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
indices = np.linspace(0, total_frames-1, num_frames, dtype=int)
for idx in indices:
cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
ret, frame = cap.read()
if not ret:
break
frame = cv2.resize(frame, (frame_size, frame_size))
frames.append(frame[..., ::-1]) # BGR to RGB
cap.release()
# 填充或截断至num_frames长度
if len(frames) < num_frames:
padding = [frames[-1]] * (num_frames - len(frames))
frames.extend(padding)
frames = frames[:num_frames]
rgb_stack = np.stack(frames, axis=0) / 255.0
# 计算光流(简化演示:此处可集成MediaPipe FlowCalculator等)
flow_stack = compute_tvl1_flow(frames) # 需自行实现或调用现有光流提取器
return np.expand_dims(rgb_stack, axis=0), np.expand_dims(flow_stack, axis=0)
加载模型并执行预测:
with tf.Session() as sess:
rgb_saver.restore(sess, 'checkpoints/rgb_scratch/model.ckpt')
flow_saver.restore(sess, 'checkpoints/flow_scratch/model.ckpt')
rgb_data, flow_data = extract_rgb_and_flow('sample_video.mp4')
feed_dict = {rgb_input: rgb_data, flow_input: flow_data}
rgb_out, flow_out = sess.run([rgb_logits, flow_logits], feed_dict)
final_logits = rgb_out + flow_out # 双流融合
# 获取Top-5预测类别
top_indices = np.argsort(final_logits[0])[::-1][:5]
print('Top predictions:', top_indices)
微调技巧
在自定义数据集上微调时,建议冻结底层卷积,仅训练顶部分类层。同时可混合使用RGB与光流模态提升准确率。通常使用ADAM优化器,初始学习率1e-4,并在验证损失停滞时衰减。
相关生态
围绕I3D的工具体系还包括:
- MediaPipe – 提供高效的视频预处理与光流计算流水线;
- TF-Hub – 可直接获取已封装的I3D模块,简化部署流程;
- Charades – 多模态视频理解基准,I3D曾在该挑战中取得优异成绩。