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)许可:允许复制、修改与非商业性再分发,须保留署名并注明修改。