File size: 13,984 Bytes
9aec0ed e853528 9aec0ed 5303c9b 9aec0ed 65effbe 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed 5303c9b 9aec0ed e853528 f68f079 9aec0ed f68f079 9aec0ed e853528 9aec0ed f68f079 9aec0ed 5303c9b 625b06d 5303c9b 9aec0ed f68f079 9aec0ed f68f079 e38e57a f68f079 9aec0ed 2f55f1e 9aec0ed | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | ---
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)许可:允许复制、修改与非商业性再分发,须保留署名并注明修改。
|