mcpField
S
scikit-video

scikit-video

github.com/tondevrel数据与数据库2445 次安装39 周前更新
代码仓库

关于 scikit-video

scikit-video 是面向科学计算和视频研究的 Python 工具包,通过 NumPy 接口处理视频,并依赖 FFmpeg 读写媒体。它提供运动估计、视频质量评估和逐帧读取,适用于视频分析与数据集制作。

主要功能

  1. 01通过 FFmpeg 读写视频
  2. 02以 NumPy 数组表示视频帧
  3. 03生成器式逐帧读取大文件
  4. 04计算运动估计与质量指标
  5. 05支持原始 YUV 数据处理

适用场景

  1. 01从长视频提取指定片段
  2. 02比较原始与压缩视频质量
  3. 03为机器学习制作视频数据集
  4. 04分析科学录像中的时间变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tondevrel/scientific-agent-skills --skill scikit-video

安装后在 Claude Code 中输入/scikit-video确认已加载。

详细介绍

scikit-video - 科学视频处理

scikit-video 通过提供基于 NumPy 的统一接口,简化了复杂的视频编解码器和容器。它支持计算运动矢量、评估视频质量(VQA),并可与其他科学 Python 技术栈无缝集成。

适用场景

  • 通过 FFmpeg 读取和写入各种格式(MP4、AVI、MKV)的视频文件。
  • 从长视频中提取特定帧或片段,无需将整个视频加载到内存中。
  • 计算运动估计(块匹配、光流)。
  • 测量视频质量(PSNR、SSIM、VIF、NIQE)。
  • 为机器学习生成视频数据集。
  • 可视化像素数据随时间的变化(例如,科学记录)。
  • 处理原始 YUV 数据流。

参考文档

官方文档:http://www.scikit-video.org/
GitHub:https://github.com/scikit-video/scikit-video
搜索模式:skvideo.io.vread、skvideo.io.FFmpegReader、skvideo.motion、skvideo.measure

核心原则

将视频视为 4D 数组

视频表示为形状为 (T, H, W, C) 的 NumPy 数组:

  • T:时间(帧数)
  • H:高度
  • W:宽度
  • C:通道(通常 RGB 为 3)
FFmpeg 后端

Scikit-video 不包含自己的编解码器,而是作为 FFmpeg 的桥接层。要让 skvideo.io 正常运行,必须在系统上安装 FFmpeg。

使用生成器处理大型数据

对于长视频,scikit-video 提供基于生成器的读取器(vreader),可逐帧处理视频,避免耗尽 RAM。

快速参考

安装
pip install scikit-video
# Note: Ensure ffmpeg is in your system PATH
常规导入
import skvideo.io
import skvideo.motion
import skvideo.measure
import numpy as np
基本模式 - 读取和检查
import skvideo.io

# 1. Read the whole video into a NumPy array
# Shape: (frames, height, width, 3)
video_data = skvideo.io.vread("experiment.mp4")

# 2. Get basic info
n_frames, height, width, channels = video_data.shape
print(f"FPS: {n_frames / 10}, Resolution: {width}x{height}")

# 3. Access a specific frame
frame_10 = video_data[10]

关键规则

✅ 应做事项
  • 大文件使用 vreader - 对高分辨率或较长的视频,始终使用基于生成器的读取方式。
  • 设置 num_frames - 如果知道所需的帧数,请指定该值,以避免不必要的扫描。
  • 检查 FFmpeg 路径 - 如果 FFmpeg 安装在非标准位置,请使用 skvideo.setFFmpegPath()。
  • 规范化指标输入 - 确保像素值处于 skvideo.measure 预期的范围内(通常 uint8 为 [0, 255])。
  • 简单输出使用 vwrite - 它会为你处理复杂的 FFmpeg 命令行参数。
  • 考虑使用 YUV - 处理原始传输数据时,请使用专门的 YUV 读取功能。
❌ 不应做的事项
  • 不要使用 vread 加载 4K 视频 - 1 分钟的 4K 视频会超出大多数 RAM 的容量。
  • 不要忽略 inputdict 和 outputdict - 这两个参数可用于向 FFmpeg 传递特定标志(如比特率、像素格式或编解码器)。
  • 不要假定通道顺序为 RGB - 读取后务必检查通道顺序,尤其是在使用外部编解码器时。
  • 不要在不降噪的情况下处理视频 - 视频噪声会影响运动估计;请先应用空间或时间滤波器。

反模式(绝对不要)

import skvideo.io

# ❌ BAD: Loading a massive file at once
# video = skvideo.io.vread("huge_4k_recording.mp4") # CRASH!

# ✅ GOOD: Processing frame by frame
reader = skvideo.io.vreader("huge_4k_recording.mp4")
for frame in reader:
    # Process frame
    pass

# ❌ BAD: Manual frame writing in a loop with manual codec setup
# (Fragile and complex)

# ✅ GOOD: Use FFmpegWriter
writer = skvideo.io.FFmpegWriter("output.mp4")
for frame in processed_frames:
    writer.writeFrame(frame)
writer.close()

# ❌ BAD: Relying on system default FFmpeg without checking
# ✅ GOOD: Verify backend
# print(skvideo._HAS_FFMPEG)

读取和写入(skvideo.io)

高级视频 I/O
import skvideo.io

# 1. Reading with specific FFmpeg options
input_parameters = {
    "-ss": "00:00:10", # Start at 10 seconds
    "-t": "5"          # Duration 5 seconds
}
video = skvideo.io.vread("video.mp4", inputdict=input_parameters)

# 2. Writing with specific bitrate and codec
output_parameters = {
    "-vcodec": "libx264",
    "-b:v": "5000k", # 5 Mbps bitrate
    "-pix_fmt": "yuv420p"
}
skvideo.io.vwrite("output.mp4", video, outputdict=output_parameters)

运动估计(skvideo.motion)

计算运动
from skvideo.motion import blockMotion
from skvideo.io import vread

# Load two consecutive frames
video = vread("video.mp4")
frame1 = video[0]
frame2 = video[1]

# Block matching algorithm
# Returns motion vectors for each block
motion_vectors = blockMotion(frame1, frame2, method='DS', mbSize=16)

# motion_vectors shape: (H/mbSize, W/mbSize, 2)
# The last dimension contains (dy, dx) offsets

视频质量评估(skvideo.measure)

测量失真
from skvideo.measure import psnr, ssim, mse

# Compare original and compressed video
original = vread("original.mp4")
distorted = vread("compressed.mp4")

# Calculate metrics frame by frame
psnr_scores = psnr(original, distorted)
ssim_scores = ssim(original, distorted)

print(f"Average PSNR: {np.mean(psnr_scores)}")

数据集和实用工具

使用内置数据集
import skvideo.datasets

# Load a built-in sample video (useful for testing)
path = skvideo.datasets.bigbuckbunny()
reader = skvideo.io.vreader(path)

实用工作流

1. 简单的背景减除流程
def extract_background(video_path):
    """Calculates the static background of a video using the median."""
    reader = skvideo.io.vreader(video_path)
    frames = []
    # Sample every 10th frame to save memory
    for i, frame in enumerate(reader):
        if i % 10 == 0:
            frames.append(frame)
        if len(frames) > 50: break
            
    # Background is the median of frames
    background = np.median(np.array(frames), axis=0).astype(np.uint8)
    return background

# Usage
# bg = extract_background("security_cam.mp4")
2. 视频稳定(帧对齐)
def stabilize_frames(video_array):
    """Very basic stabilization using motion vectors."""
    stabilized = [video_array[0]]
    for i in range(1, len(video_array)):
        motion = skvideo.motion.blockMotion(video_array[i-1], video_array[i])
        avg_motion = np.mean(motion, axis=(0, 1)) # Global drift
        # Translate frame back (Simplified logic)
        # Use scipy.ndimage.shift for actual translation
        ...
3. 自动生成视频质量报告
def generate_vqa_report(ref_path, test_path):
    ref = skvideo.io.vread(ref_path)
    test = skvideo.io.vread(test_path)
    
    report = {
        "MSE": np.mean(skvideo.measure.mse(ref, test)),
        "PSNR": np.mean(skvideo.measure.psnr(ref, test)),
        "SSIM": np.mean(skvideo.measure.ssim(ref, test))
    }
    return report

性能优化

使用 vreader 进行多线程处理

如果要对每一帧执行大量处理,请采用基于队列的多线程方法,让 FFmpeg 管道保持满载。

高效切片

不要先使用 vread 再切片,而应通过 inputdict 使用 FFmpeg 的 seek 和 duration 标志,只从磁盘读取所需的数据。

常见问题及解决方案

找不到 FFmpeg

Scikit-video 依赖 ffmpeg 可执行文件。

# ✅ Solution: Manually set the path if it's not in environment
import skvideo
skvideo.setFFmpegPath("C:/ffmpeg/bin")
色彩空间不匹配

有些视频以 YUV422 或 YUV444 格式存储。Scikit-video 默认会将其转换为 RGB。

# ❌ Problem: Colors look washed out or incorrect
# ✅ Solution: Specify the pixel format in inputdict
reader = skvideo.io.vreader("video.mp4", inputdict={"-pix_fmt": "yuv420p"})
内存不足(OOM)错误

即使使用 vreader,如果将所有帧都存储在列表中,最终也会耗尽内存。

# ❌ Problem: frames.append(frame) in a loop
# ✅ Solution: Process and save to disk, or clear the list periodically.

scikit-video 将 FFmpeg 的强大功能带入 NumPy 世界。它通过抽象视频容器的复杂性,并提供运动估计和质量指标等科学分析工具,成为所有处理时序图像数据的研究人员必不可少的工具。

评论

支持 Markdown