|
Download README.md from Sudabaka/SFDP-Siamese-NET-AI: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/Sudabaka/SFDP-Siamese-NET-AI/resolve/main/README.md
- Command line
-
hf download hf://Sudabaka/SFDP-Siamese-NET-AI/README.md
-
curl -L -o README.md https://huggingface.co/Sudabaka/SFDP-Siamese-NET-AI/resolve/main/README.md
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)许可:允许复制、修改与非商业性再分发,须保留署名并注明修改。 | |