Easy4K SFDP · Siamese NET AI

面向视频帧去重的轻量孪生网络。输入相邻两帧的同一位置灰度块,输出 0~1 的连续相似度, 用于识别 1 拍 2 / 1 拍 3 等重复帧场景。模型通过知识蒸馏复现 Easy4K SFDP 四阶判决器 (像素差、dHash、QR 分解、Farnebäck 光流)的判定行为,可在 NVIDIA / AMD / Intel 显卡上 通过 DirectML 统一推理。

训练数据声明

本模型在训练过程中未分发、未再发布任何原始视频、音频或视频帧。训练仅使用从公开网络获取的视频中抽取的灰度切片,且全部监督信号由 Easy4K 自研的 SFDP 四阶判重判决器(像素差 / dHash / QR 码 / Farnebäck 光流)自动生成,不含人工标注。

视频著作权归原作者所有。所用素材清单见 training-materials.txt(含标题、BV 号、UP 主、原始链接),仅用于说明数据来源,不构成对原作品的授权或再分发。

若权利人认为其作品不应被用于本研究,请提交 issue,我们将在 72 小时内从清单中移除,并在后续版本训练中排除该来源。

模型权重以 CC BY-NC 4.0 发布,仅限研究与非商业用途。模型输出为 0~1 的相似度分数,不具备生成、重建或复现原视频内容的能力。

模型详情

项目 说明
开发者 Sudabaka(Easy4K)
模型类型 孪生卷积网络(Siamese CNN),共享权重双分支
架构 深度可分离卷积编码器(6 级下采样、512 维嵌入)+ 差分/乘积融合头(1024 隐层)
参数量 2602017
输入 frame_a、frame_b:灰度 128×128,float32,范围 [0, 1],NCHW
输出 score:形状 [batch, 1],Sigmoid 后位于 [0, 1],越接近 1 越可能重复
导出格式 ONNX,opset 17,动态 batch
FP32 版本 model.onnx,约 9.95 MB,对应 Easy4K「完美模式」
FP16 版本 model_fp16.onnx,约 5 MB(内部半精度、输入输出保持 float32),对应 Easy4K「性能模式」
运行后端 onnxruntime:DmlExecutionProvider(DirectML)/ CPUExecutionProvider
建议阈值 0.5;需要更低误判时可用 0.6~0.7
许可证 CC BY-NC 4.0(仅限非商业用途)

快速开始

1. 安装依赖

# Windows(NVIDIA / AMD / Intel 统一走 DirectML)
pip install onnxruntime-directml numpy opencv-python

# Linux / macOS(纯 CPU)
pip install onnxruntime numpy opencv-python

2. 选择模型文件

场景 文件 阈值建议
精度优先(对应 Easy4K 完美模式) model.onnx(FP32,9.95 MB) 0.5
速度优先(对应 Easy4K 性能模式) model_fp16.onnx(FP16,5.01 MB) 0.55~0.6

两份模型的输入输出签名完全一致,切换只需换文件名。FP16 版本内部半精度、输入输出仍是 float32,调用代码不用改。

3. 最小可运行示例

import numpy as np
import onnxruntime as ort

providers = [p for p in ("DmlExecutionProvider", "CPUExecutionProvider")
             if p in ort.get_available_providers()]
sess = ort.InferenceSession("model.onnx", providers=providers)

# 同位置的两块灰度图,[0,1],NCHW
a = np.random.rand(1, 1, 128, 128).astype(np.float32)
b = a.copy()

score = float(sess.run(["score"], {"frame_a": a, "frame_b": b})[0][0, 0])
print(score)              # 越接近 1 越可能是重复帧
print(score >= 0.5)       # 判重结果

4. 从视频帧取块(预处理规范)

预处理必须与训练时一致,否则分数不可信:

  1. 解码后先转灰度
  2. 在原分辨率下裁剪出 128×128 的块(不要先缩放整帧再裁)
  3. 归一化到 [0, 1],float32
  4. 排列为 NCHW,单样本即 (1, 1, 128, 128)
  5. 两个输入块必须是同一坐标位置
import cv2
import numpy as np

def patch(gray, x, y, size=128):
    p = gray[y:y + size, x:x + size]
    if p.shape[:2] != (size, size):
        return None
    return (p.astype(np.float32) / 255.0)[None, None, :, :]

cap = cv2.VideoCapture("input.mp4")
ok, f1 = cap.read()
ok2, f2 = cap.read()
g1 = cv2.cvtColor(f1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(f2, cv2.COLOR_BGR2GRAY)

a, b = patch(g1, 320, 180), patch(g2, 320, 180)
if a is not None and b is not None:
    s = float(sess.run(["score"], {"frame_a": a, "frame_b": b})[0][0, 0])
    print("duplicate" if s >= 0.5 else "different", s)

5. 批量推理

batch 维度是动态的,一次送入多个帧对可显著提高吞吐(DirectML 下比逐对调用快 2~4 倍):

pairs_a = np.concatenate([a] * 32, axis=0)   # (32, 1, 128, 128)
pairs_b = np.concatenate([b] * 32, axis=0)
scores = sess.run(["score"], {"frame_a": pairs_a, "frame_b": pairs_b})[0].ravel()  # (32,)

6. 阈值调法

阈值 效果
0.5 默认,偏召回,适合“宁可多判不放过”
0.6~0.7 偏精确,适合画面干净、误判代价高的场景

判断依据:若实际使用中误删真正不同的帧(漏检画面),就调高;若放过重复帧,就调低。

7. 常见问题

现象 原因与处理
DmlExecutionProvider 不可用 未装 onnxruntime-directml,或系统缺少 DirectX 12;会自动回退 CPU,不影响结果
报输入维度错误 必须是 (N, 1, 128, 128)、float32;FP16 模型也接收 float32 输入
分数恒为 0 或恒为 1 检查是否忘了 /255、是否用了彩色三通道、是否两块取自不同位置
结果和 Easy4K 不一致 预处理路径不同(先缩放 vs 先裁剪)、阈值不同,或用了 FP16 版本

完整可运行示例见 example_infer.py。

使用场景

适用

  • 视频补帧 / 超分前的重复帧检测,尤其是动画 1 拍 2、1 拍 3 的帧复用;
  • 作为 Easy4K SFDP 的快速前置筛选,降低后续 QR 与光流计算的调用次数;
  • 需要跨厂商 GPU 统一推理路径的桌面端场景(DirectML 单套算子覆盖三家)。

不适用

  • 整帧级、跨场景的重复镜头检索(模型只判断 128×128 局部块);
  • 经过强压缩、去噪、缩放等处理后的一致性判定(训练分布未覆盖);
  • 需要逐像素级精确对齐的场合,本模型输出的是相似度分数而非位移场。

训练方法

教师与标签

教师为 Easy4K 生产环境的 SFDP 完美模式(四阶全开)。对每个样本同时记录判决阶段与中间指标:

  • 教师判重且光流位移为 0:软标签 1.0;
  • 教师判重但存在可测位移:软标签 clip(1 - flow / 2.0, 0, 1);
  • 教师在光流阶段判否:同样按上式映射,光流 0.1~0.4 的模糊区丢弃;
  • 教师在前三阶判否:明确负样本,软标签 0;
  • 第一阶段判为相同、被光流救回的样本标记为 hard,损失权重 2.0。

数据

项目 数值
素材来源 Wikimedia Commons(CC BY / CC BY-SA / CC0);用户提供的术力口 / 真人 MV;Bilibili 公开 MV(仅训练使用,不随模型分发)
片段构造 固定窗口连续帧,按 1拍1 / 1拍2 / 1拍3 / 混合节奏展开,本版本使用其中 5212 个片段
样本总数 550158(训练 472011 / 验证 78147)
正负比 1 : 1.00
难例 9972 个(光流救回,权重 2.0)
划分方式 按来源视频隔离,验证集素材不参与训练

完整素材清单(462 支视频 / 7852 个切片,含标题、作者、许可证与来源链接)单独发布于 Sudabaka/SFDP-Siamese-NET-AI-Dataset; 本版本模型基于该数据集的 5212 片段快照训练。

训练配置

项目 值
目标函数 软标签 MSE 回归(非二分类交叉熵)
优化器 AdamW,weight decay 1e-4
学习率 2e-3,2 epoch 线性 warmup + 余弦退火
Batch size 256
Epoch 8
硬件 NVIDIA P106-100(6 GB),CUDA 12.4,PyTorch 2.6.0

完整实现代码

模型训练、导出与数据来源记录的全部实现代码随仓库提供,位于 code/:

文件 作用
code/siai_all.py 一体化流水线:视频切片(tiles)、教师打标(teacher)、软标签生成(label)、训练(train)、评测(eval)、ONNX 导出(pack)
code/teacher_run.py 教师打标的轻量入口:只做目录扫描与 SfdpTeacher 调用,不加载 torch / cv2,避免与训练同时运行时内存不足
code/append_sources.py 训练素材清单的生成与去重追加,产出可溯源的 training-materials.txt
code/algorithm/FrameDedupService.cs 四阶判决器教师本体:像素差粗筛 → dHash 细筛 → QR 分解精判 → Farnebäck 光流终判,含全部阈值与标定注释
code/algorithm/FarnebackFlow.cs 第四阶使用的稠密光流实现(GPU/CPU 混合路径)
code/algorithm/Easy4K.SFDP.csproj 上述两个源文件的编译工程(.NET 10,Windows.Graphics.Imaging)

教师算法(四阶判决器)

阶段 方法 作用
1 像素绝对差均值(MAD) 粗筛,明显不同的帧对直接放过
2 dHash 汉明距离 细筛,感知哈希不一致的帧对放过
3 8×8 分块 QR 分解,取 diag(R) 特征算 Minkowski 距离 精判,抑制亮度/压缩噪声造成的误判
4 Farnebäck 稠密光流,统计均值与方差 终判,区分“真重复帧”与“相似但不相同”的运动画面

阈值取论文建议值并对 1080p 动画 MV 重新标定(τ_flow=0.5、τ_var=0.1、QR 阈值 1.0 灰阶),标定过程与分布数据写在源码注释里。

ONNX 模型

文件 精度 体积 建议用途
model.onnx FP32 9.95 MB 完美模式(精度优先)
model_fp16.onnx FP16(IO 保持 float32) 5.01 MB 性能模式(速度优先,DirectML 下约快 1.5~2 倍)

两份模型输入输出签名完全一致:frame_a、frame_b → score,调用方按模式切换文件名即可。

主要命令:

# 1) 从视频抽取灰度切片
python code/siai_all.py tiles --raw <视频目录> --segments 4 --out <切片目录>

# 2) 用四阶判决器教师生成逐片段标签 CSV
python code/siai_all.py teacher --tiles <切片目录> --labels <标签目录>

# 3) 生成软标签训练集与验证集
python code/siai_all.py label

# 4) 训练(结束后自动导出 FP32 与 FP16 两份 ONNX)
python code/siai_all.py train --out <输出目录> --epochs 1 --workers 8 --lr 1e-4

# 5) 评测 / 打包
python code/siai_all.py eval  --out <输出目录>
python code/siai_all.py pack  --onnx <输出目录>/easy4k_sfdp_siamese_fp32.onnx --out <发布目录>

依赖见 requirements.txt(PyTorch、OpenCV、onnx、onnxruntime、onnxconverter-common)。教师端二进制 SfdpTeacher 属于 Easy4K 应用程序的一部分,不随本仓库分发。

评测结果

与教师的一致性(验证集 78147 样本,按视频隔离)

指标 数值
软标签 MAE 0.02788
判决准确率(阈值 0.5) 97.56%
精确率 / 召回率 97.42% / 98.11%
正样本 MAE 0.01063
负样本 MAE 0.04085

推理性能

硬件 后端 批量 每对耗时
AMD Radeon RX 580 DirectML 1.24.4(Windows 11) 64 0.56 ms
NVIDIA P106-100 CPU 执行器 32 0.317 ms

数值一致性

ONNX 与 PyTorch 输出最大绝对误差不超过 1.2e-7,可直接替换训练端推理。

局限与风险

  • 题材覆盖:训练素材以实拍街景、开源动画与音乐视频为主,番剧 1 拍 2 / 1 拍 3 的真实样本 仍有限,建议在目标内容上先做小规模验证再上线。
  • 局部判定:模型只看 128×128 灰度块,不理解整帧语义;涉及大面积平移、缩放、转场的 判定仍需上层聚合逻辑。
  • 压缩与后处理:强压缩块效应、降噪、锐化会改变像素分布,可能影响分数校准。
  • 系统要求:DirectML 需要 Windows 10 1903+ 或 Windows 11;更旧的系统需回退 CPU。
  • 蒸馏上限:模型逼近教师而非超越教师,教师判错的样本同样会被学习。
  • 许可证:CC BY-NC 4.0 禁止商业性使用;商业发行需另行授权。

引用

@misc{easy4k_sfdp_siamese_net_ai,
  author       = {Sudabaka},
  title        = {Easy4K SFDP - Siamese NET AI},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/Sudabaka/SFDP-Siamese-NET-AI}},
  note         = {Frame-duplicate similarity model distilled from the Easy4K SFDP judge}
}

致谢

  • CC 训练素材来自 Wikimedia Commons,遵循各自 CC BY / CC BY-SA / CC0 许可,完整作者与许可证信息见 sources.json;
  • 教师模型与推理实现来自 Easy4K SFDP(帧去重四阶判决器);
  • 跨厂商推理基于 ONNX Runtime DirectML。

许可证

模型权重与示例代码采用 Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)许可:允许复制、修改与非商业性再分发,须保留署名并注明修改。

Downloads last month
83
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train Sudabaka/SFDP-Siamese-NET-AI