SFDP-Siamese-NET-AI / README.md
Sudabaka's picture
chore: 同步最新实现代码(FP16 导出 / 轻量教师入口)与更新后的训练素材清单
625b06d verified
|
Raw History Blame Contribute Delete
14 kB
---
license: cc-by-nc-4.0
library_name: onnxruntime
tags:
- video
- frame-deduplication
- siamese-network
- knowledge-distillation
- onnx
- directml
datasets:
- wikimedia-commons
- Sudabaka/SFDP-Siamese-NET-AI-Dataset
---
# 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. 安装依赖
```bash
# 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. 最小可运行示例
```python
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. 两个输入块必须是**同一坐标位置**
```python
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 倍):
```python
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](https://huggingface.co/datasets/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):
| 文件 | 作用 |
|---|---|
| `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`,调用方按模式切换文件名即可。
主要命令:
```bash
# 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 禁止商业性使用;商业发行需另行授权。
## 引用
```bibtex
@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](https://commons.wikimedia.org/),遵循各自 CC BY /
CC BY-SA / CC0 许可,完整作者与许可证信息见 `sources.json`;
- 教师模型与推理实现来自 Easy4K SFDP(帧去重四阶判决器);
- 跨厂商推理基于 ONNX Runtime DirectML。
## 许可证
模型权重与示例代码采用
[Creative Commons Attribution-NonCommercial 4.0 International](https://creativecommons.org/licenses/by-nc/4.0/)
(CC BY-NC 4.0)许可:允许复制、修改与非商业性再分发,须保留署名并注明修改。