mcpField
V
video-processing

video-processing

github.com/letta-ai数据与数据库152189 次安装4 周前更新
代码仓库

关于 video-processing

为使用 OpenCV 等计算机视觉库处理和分析视频提供指导的技能。它强调先检查帧和元数据,再开发并验证事件检测或运动跟踪逻辑。

主要功能

  1. 01检查样例帧和视频元数据
  2. 02构建事件检测流程
  3. 03使用帧差和轮廓检测
  4. 04跟踪物体随时间的位置
  5. 05验证时间合理性并测试多段视频

适用场景

  1. 01排查视频片段中的事件检测
  2. 02开发运动跟踪逻辑
  3. 03用已知帧验证检测结果
  4. 04调试不稳定的视频分析

安装

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

$npx skills add https://github.com/letta-ai/skills --skill video-processing

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

详细介绍

视频处理

概述

本技能为使用 OpenCV 等计算机视觉库执行视频处理任务提供指导,涵盖帧级分析、事件检测和运动跟踪。它强调验证优先的方法,并帮助避免视频分析工作流中常见的陷阱。

核心方法:先验证,再实现

在编写检测算法之前,先准确了解视频内容:

  1. 提取并检查样例帧 - 将关键帧保存为图像,以直观确认特定帧中发生的情况
  2. 了解视频元数据 - 帧数、FPS、时长、分辨率
  3. 将预期事件映射到帧范围 - 如果存在测试数据,了解哪些帧对应哪些事件
  4. 先构建诊断工具 - 帧提取和可视化工具能提供关键线索

事件检测任务的工作流

阶段 1:探索视频
# Essential first steps for any video analysis task
import cv2

cap = cv2.VideoCapture(video_path)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = cap.get(cv2.CAP_PROP_FPS)
duration = frame_count / fps

print(f"Frames: {frame_count}, FPS: {fps}, Duration: {duration:.2f}s")

重要:提取预期事件位置的帧,以确认理解是否正确:

def save_frame(video_path, frame_num, output_path):
    cap = cv2.VideoCapture(video_path)
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
    ret, frame = cap.read()
    if ret:
        cv2.imwrite(output_path, frame)
    cap.release()

# Save frames at expected event times for visual inspection
save_frame("video.mp4", 50, "frame_050.png")
save_frame("video.mp4", 60, "frame_060.png")
阶段 2:开发算法

开发检测算法时:

  1. 从简单方法开始 - 先尝试基本的帧差分或阈值处理,再使用复杂方法
  2. 使用可配置的阈值 - 避免硬编码神奇数字;根据数据推导阈值
  3. 先在已知帧上测试 - 在已知真实情况的帧上验证算法是否能产生预期结果
  4. 记录中间值 - 跟踪每一帧的指标,了解算法的行为
阶段 3:验证

定稿前:

  1. 对输出进行合理性检查 - 检测到的事件在顺序和时间上是否合理?
  2. 在多个视频上测试 - 验证算法能否泛化到不同输入
  3. 与预期范围进行比较 - 如果存在真实情况数据,验证检测准确性

常见检测方法

帧差分

将帧与参考帧(第一帧或前一帧)进行比较,以检测运动:

# Background subtraction approach
first_frame = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)
first_frame = cv2.GaussianBlur(first_frame, (21, 21), 0)

# For each subsequent frame
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
diff = cv2.absdiff(first_frame, gray)

陷阱:如果场景发生变化或摄像机移动,第一帧可能不适合作为参考帧。

基于轮廓的检测

通过在阈值处理后的图像中查找轮廓来识别对象:

_, thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

陷阱:未经校准,阈值(例如 25)和轮廓最小面积都只是任意值。

跟踪随时间变化的位置

要检测跳跃或手势等事件,可跟踪对象在各帧中的位置:

positions = []  # (frame_num, x, y, area) tuples
for frame_num in range(frame_count):
    # ... detection code ...
    if detected:
        positions.append((frame_num, cx, cy, area))

陷阱:坐标系很重要。在图像坐标中,Y 轴向下增大,因此“在帧中位置更高”意味着 Y 值更小。

验证策略

1. 目视检查

保存检测到事件时的帧,以确认结果是否正确:

# After detecting takeoff at frame N
save_frame(video_path, detected_takeoff, "detected_takeoff.png")
save_frame(video_path, detected_takeoff - 5, "before_takeoff.png")
save_frame(video_path, detected_takeoff + 5, "after_takeoff.png")
2. 时序合理性

检查检测到的事件在时间上是否合理:

duration_seconds = frame_count / fps
event_time = detected_frame / fps

# Example: A jump in a 4-second video shouldn't be detected in the last 0.5 seconds
if event_time > duration_seconds - 0.5:
    print("WARNING: Event detected very late in video - verify correctness")
3. 序列验证

确保事件按逻辑顺序发生:

if detected_landing <= detected_takeoff:
    print("ERROR: Landing cannot occur before or at takeoff")
4. 多视频测试

尽早在多个输入上测试,以发现算法对单个视频特征过拟合的问题。

常见陷阱

1. 未验证真实情况

问题:完全依赖计算出的指标,却不进行目视确认。

解决方案:始终保存并检查检测到事件位置的帧。

2. 数据解读中的确认偏误

问题:当数据呈现意外模式时,编造符合先入之见的解释,而不是质疑原有假设。

解决方案:如果检测结果看起来不对,应调查根本原因,而不是为意外行为找理由。

3. 神奇数字阈值

问题:使用任意阈值(轮廓面积取 500、二值阈值取 25),却没有实证依据。

解决方案:根据实际视频数据推导阈值,或将其设为可配置参数并提供合理的默认值。

4. 忽视检测缺失区间

问题:检测在一段帧范围内失败时,未经调查就认定这是预期行为。

解决方案:调查检测失败的原因——这可能表明算法存在缺陷,而不是预期行为。

5. 坐标系混淆

问题:误解 Y 坐标(在图像坐标系中,Y 值越小,位置越靠近画面上方)。

解决方案:明确记录坐标系假设,并通过目视检查进行验证。

6. 忽略时间合理性

问题:接受在时间上不合理的检测结果(例如,在一段 4 秒视频的最后 0.8 秒检测到事件)。

解决方案:对输出时间实现合理性检查。

7. 对单个视频过拟合

问题:算法在一个视频上有效,但在其他视频上失效。

解决方案:在开发早期就在多个视频上进行测试。

输出格式注意事项

输出结果时(例如,输出为 TOML、JSON):

import numpy as np

# Convert numpy types to Python native types for serialization
result = {
    "takeoff_frame": int(takeoff_frame),  # Not np.int64
    "landing_frame": int(landing_frame),
}

调试检查清单

检测结果不正确时:

  1. 我是否目视检查了预期事件发生时间的帧?
  2. 我是否目视检查了检测到的事件发生时间的帧?
  3. 根据视频时长,我检测到的时间在时间上是否合理?
  4. 我是否在具有已知真值的帧上验证了算法?
  5. 我是否正确理解了坐标系?
  6. 我是否在多个视频上进行了测试?
  7. 我的阈值是根据数据得出的,还是随意设定的?
  8. 当某些帧检测失败时,我是否了解原因?

评论

支持 Markdown