🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://skills.sh/aradotso/trending-skills/corridorkey-green-screen

💡 提示:需要 Node.js 和 NPM

CorridorKey 绿幕抠像

技能来自 ara.so — Daily 2026 Skills 系列。

CorridorKey 是一个神经网络,用于解决绿幕素材中的颜色解混问题。对于每一个像素——包括运动模糊、头发或失焦边缘产生的半透明像素——它能预测出真实的前景颜色(未预乘)和干净的线性 Alpha 通道。它支持读写 16 位和 32 位 EXR 文件,以便与 VFX 流程集成。

工作原理

每帧需要两个输入:

  1. RGB 绿幕图像 — sRGB 或线性伽马,sRGB/REC709 色域
  2. Alpha 提示 — 粗糙的黑白遮罩(不需要精确)

模型会根据提示填充精细细节;它在模糊/腐蚀的遮罩上进行训练。

安装

先决条件

  • uv 包管理器(自动处理 Python)
  • 支持 CUDA 12.8+ 驱动程序的 NVIDIA GPU(适用于 GPU),或 Apple M1+(适用于 MLX),或 CPU 备用方案

Windows

# 双击或从终端运行:
Install_CorridorKey_Windows.bat

# 可选的重型模块:
Install_GVM_Windows.bat
Install_VideoMaMa_Windows.bat

Linux / macOS

# 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 安装依赖 — 选择一项:
uv sync                  # CPU / Apple MPS (通用)
uv sync --extra cuda     # NVIDIA GPU (Linux/Windows)
uv sync --extra mlx      # Apple Silicon MLX

# 下载所需的模型 (~300MB)
mkdir -p CorridorKeyModule/checkpoints
# 将下载的 CorridorKey_v1.0.pth 放置为:
# CorridorKeyModule/checkpoints/CorridorKey.pth

模型下载地址:https://huggingface.co/nikopueringer/CorridorKey_v1.0/resolve/main/CorridorKey_v1.0.pth

可选的 Alpha 提示生成器

# GVM (自动生成,~80GB 显存,适用于人物)
uv run hf download geyongtao/gvm --local-dir gvm_core/weights

# VideoMaMa (需要遮罩提示,通过社区调整后 <24GB 显存)
uv run hf download SammyLim/VideoMaMa \
  --local-dir VideoMaMaInferenceModule/checkpoints/VideoMaMa

uv run hf download stabilityai/stable-video-diffusion-img2vid-xt \
  --local-dir VideoMaMaInferenceModule/checkpoints/stable-video-diffusion-img2vid-xt \
  --include "feature_extractor/*" "image_encoder/*" "vae/*" "model_index.json"

主要 CLI 命令

# 在准备好的片段上运行推理
uv run python main.py run_inference --device cuda
uv run python main.py run_inference --device cpu
uv run python main.py run_inference --device mps   # Apple Silicon

# 列出可用的片段/镜头
uv run python main.py list

# 交互式设置向导
uv run python main.py wizard
uv run python main.py wizard --win_path /path/to/ClipsForInference

Docker (Linux + NVIDIA GPU)

# 构建镜像
docker build -t corridorkey:latest .

# 运行推理
docker run --rm -it --gpus all \
  -e OPENCV_IO_ENABLE_OPENEXR=1 \
  -v "$(pwd)/ClipsForInference:/app/ClipsForInference" \
  -v "$(pwd)/Output:/app/Output" \
  -v "$(pwd)/CorridorKeyModule/checkpoints:/app/CorridorKeyModule/checkpoints" \
  corridorkey:latest run_inference --device cuda

# Docker Compose
docker compose build
docker compose --profile gpu run --rm corridorkey run_inference --device cuda
docker compose --profile gpu run --rm corridorkey list

# 在多 GPU 系统上固定使用特定 GPU
NVIDIA_VISIBLE_DEVICES=0 docker compose --profile gpu run --rm corridorkey run_inference --device cuda

目录结构

CorridorKey/
├── ClipsForInference/          # 输入的镜头片段存放于此
│   └── my_shot/
│       ├── frames/             # 绿幕 RGB 帧 (PNG/EXR)
│       ├── alpha_hints/        # 粗糙的 Alpha 遮罩 (灰度)
│       └── VideoMamaMaskHint/  # 可选:用于 VideoMaMa 的手绘提示
├── Output/                     # 处理结果
│   └── my_shot/
│       ├── foreground/         # 未预乘 RGBA EXR 帧
│       └── alpha/              # 线性 Alpha 通道帧
├── CorridorKeyModule/
│   └── checkpoints/
│       └── CorridorKey.pth     # 必需的模型权重
├── gvm_core/weights/           # 可选的 GVM 权重
└── VideoMaMaInferenceModule/
    └── checkpoints/            # 可选的 VideoMaMa 权重

Python 使用示例

基础推理流程

import torch
from pathlib import Path
from CorridorKeyModule.model import CorridorKeyModel  # 根据实际模块路径调整
from CorridorKeyModule.inference import run_inference

# 加载模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CorridorKeyModel()
model.load_state_dict(torch.load("CorridorKeyModule/checkpoints/CorridorKey.pth"))
model.to(device)
model.eval()

# 在镜头文件夹上运行推理
run_inference(
    shot_dir=Path("ClipsForInference/my_shot"),
    output_dir=Path("Output/my_shot"),
    device=device,
)

读写 EXR 文件

import cv2
import numpy as np
import os

os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"

# 读取 32 位线性 EXR 帧
frame = cv2.imread("frame_0001.exr", cv2.IMREAD_UNCHANGED | cv2.IMREAD_ANYCOLOR)
# frame 是 float32 类型,线性光,BGR 通道顺序

# 将 BGR 转换为 RGB 以便处理
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

# 写入输出 EXR (未预乘 RGBA)
# 假设 `foreground` 是 float32 HxWx4 (RGBA, 线性, 未预乘 Alpha)
foreground_bgra = cv2.cvtColor(foreground, cv2.COLOR_RGBA2BGRA)
cv2.imwrite("output_0001.exr", foreground_bgra.astype(np.float32))

使用 OpenCV 生成粗糙 Alpha 提示

import cv2
import numpy as np

def generate_chroma_key_hint(image_bgr: np.ndarray, erode_px: int = 5) -> np.ndarray:
    """
    快速生成绿幕提示,用于 CorridorKey 输入。
    返回灰度遮罩 (0=背景, 255=前景)。
    """
    hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)

    # 根据你的具体绿幕调整这些范围
    lower_green = np.array([35, 50, 50])
    upper_green = np.array([85, 255, 255])

    green_mask = cv2.inRange(hsv, lower_green, upper_green)
    foreground_mask = cv2.bitwise_not(green_mask)

    # 腐蚀使遮罩远离边缘(CorridorKey 处理边缘细节)
    kernel = np.ones((erode_px, erode_px), np.uint8)
    eroded = cv2.erode(foreground_mask, kernel, iterations=2)

    # 可选:轻微模糊以柔化提示
    blurred = cv2.GaussianBlur(eroded, (15, 15), 5)
    return blurred


# 使用方法
frame = cv2.imread("greenscreen_frame.png")
hint = generate_chroma_key_hint(frame, erode_px=8)
cv2.imwrite("alpha_hint.png", hint)

批量处理帧

from pathlib import Path
import cv2
import numpy as np
import os

os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"

def prepare_shot_folder(
    raw_frames_dir: Path,
    output_shot_dir: Path,
    hint_generator_fn=None
):
    """
    从原始绿幕帧准备 CorridorKey 镜头文件夹。
    """
    frames_out = output_shot_dir / "frames"
    hints_out = output_shot_dir / "alpha_hints"
    frames_out.mkdir(parents=True, exist_ok=True)
    hints_out.mkdir(parents=True, exist_ok=True)

    frame_paths = sorted(raw_frames_dir.glob("*.png")) + \
                  sorted(raw_frames_dir.glob("*.exr"))

    for frame_path in frame_paths:
        frame = cv2.imread(str(frame_path), cv2.IMREAD_UNCHANGED | cv2.IMREAD_ANYCOLOR)

        # 复制帧
        cv2.imwrite(str(frames_out / frame_path.name), frame)

        # 生成提示
        if hint_generator_fn:
            hint = hint_generator_fn(frame)
        else:
            hint = generate_chroma_key_hint(frame)

        hint_name = frame_path.stem + ".png"
        cv2.imwrite(str(hints_out / hint_name), hint)

    print(f"已在 {output_shot_dir} 中准备了 {len(frame_paths)} 帧")


prepare_shot_folder(
    raw_frames_dir=Path("raw_footage/shot_01"),
    output_shot_dir=Path("ClipsForInference/shot_01"),
)

使用 clip_manager.py 的 Alpha 提示生成器

# GVM (自动 — 无需额外输入)
from clip_manager import generate_alpha_hints_gvm

generate_alpha_hints_gvm(
    shot_dir="ClipsForInference/my_shot",
    device="cuda"
)

# VideoMaMa (首先将粗糙遮罩放在 VideoMamaMaskHint/ 目录下)
from clip_manager import generate_alpha_hints_videomama

generate_alpha_hints_videomama(
    shot_dir="ClipsForInference/my_shot",
    device="cuda"
)

# BiRefNet (轻量级选项,不需要大量显存)
from clip_manager import generate_alpha_hints_birefnet

generate_alpha_hints_birefnet(
    shot_dir="ClipsForInference/my_shot",
    device="cuda"
)

Alpha 提示最佳实践

# 良好做法:腐蚀、略微模糊的提示 — 远离边缘
# 模型会根据提示填充边缘细节
kernel = np.ones((10, 10), np.uint8)
good_hint = cv2.erode(raw_mask, kernel, iterations=3)
good_hint = cv2.GaussianBlur(good_hint, (21, 21), 7)

# 不良做法:膨胀/扩大的提示 — 模型更不擅长减掉多余部分
# 不要将遮罩向外推,超出真实主体的边界
bad_hint = cv2.dilate(raw_mask, kernel, iterations=3)  # 避免这样

# 可接受:原样使用粗糙的二进制色键遮罩
# 即使是硬边二进制遮罩也可以 — 只要没有膨胀
acceptable_hint = raw_chroma_key_mask  # 不进行膨胀

输出集成 (Nuke / Fusion / Resolve)

CorridorKey 输出的是未预乘的 RGBA EXR 文件,采用线性光:

# 在 Nuke 中:以 EXR 读取,设置色彩空间为 "linear"
# Alpha 通道已经是干净的 — 无需使用 Unpremult 节点
# 直接连接到 Merge (over) 节点与你的背景板

# 验证输出是未预乘 Alpha (非预乘):
import cv2, numpy as np, os
os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"

result = cv2.imread("Output/shot_01/foreground/frame_0001.exr",
                    cv2.IMREAD_UNCHANGED | cv2.IMREAD_ANYCOLOR)
# result[..., 3] = Alpha 通道 (线性 0.0–1.0)
# result[..., :3] = 未预乘的颜色 (未乘以 Alpha)

# 检查一个半透明像素
h, w = result.shape[:2]
sample_alpha = result[h//2, w//2, 3]
sample_color = result[h//2, w//2, :3]
print(f"Alpha: {sample_alpha:.3f}, Color: {sample_color}")
# 即使在 Alpha < 1.0 的地方,颜色值也应该是全强度的 (未预乘 Alpha)

故障排除

未检测到 CUDA / 回退到 CPU

# 检查 CUDA 版本要求:驱动程序必须支持 CUDA 12.8+
nvidia-smi  # 显示支持的最大 CUDA 版本

# 使用显式的 CUDA 额外选项重新安装
uv sync --extra cuda

# 验证 PyTorch 能否看到 GPU
uv run python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"

OpenEXR 读写失败

# 必须在导入 cv2 之前设置环境变量
export OPENCV_IO_ENABLE_OPENEXR=1
uv run python your_script.py

# 或者在 Python 中设置 (必须在导入 cv2 之前)
import os
os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"
import cv2

显存不足

# 使用 CPU 备用方案
uv run python main.py run_inference --device cpu

# 或者如果支持,减少批处理大小 / 使用分块推理
# 引擎动态缩放到 2048x2048 分块 — 对于 4K 素材,
# 确保至少有 6-8GB 显存

# Apple Silicon: 使用 MPS
uv run python main.py run_inference --device mps

找不到模型文件

# 验证确切的文件名和位置:
ls CorridorKeyModule/checkpoints/
# 必须确切命名为:CorridorKey.pth
# 而不是:CorridorKey_v1.0.pth

mv CorridorKeyModule/checkpoints/CorridorKey_v1.0.pth \
   CorridorKeyModule/checkpoints/CorridorKey.pth

Docker GPU 透传失败

# 测试 NVIDIA 容器工具包
docker run --rm --gpus all nvidia/cuda:12.6.3-runtime-ubuntu22.04 nvidia-smi

# 如果失败,安装/重新配置 nvidia-container-toolkit:
# https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html

# 然后重启 Docker 守护进程
sudo systemctl restart docker

抠像效果不佳

  • 提示太膨胀:更多地腐蚀你的 Alpha 提示 — CorridorKey 更擅长添加边缘细节,而不是移除不需要的遮罩区域
  • 色彩空间错误:确保输入是 sRGB/REC709 色域;不要直接传递对数编码的素材
  • 绿色溢出:模型处理颜色解混,但源素材中极端的绿色溢出可能会降低结果质量;考虑在推理前进行一次去溢色处理
  • 静态主体:GVM 在人物上效果最好;对于道具/物体,尝试使用手绘提示的 VideoMaMa

社区与资源

📄 原始文档

完整文档(英文):

https://skills.sh/aradotso/trending-skills/corridorkey-green-screen

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。