feat: 二次元识别功能 + 模型目录整理(nwfs/wd-tagger 子目录),修复 wd-tagger 输入维度(NHWC)

This commit is contained in:
2025-06-25 21:10:21 +08:00
parent 4efa48f550
commit 3af2bf70b4
18 changed files with 1386 additions and 21 deletions
+33 -7
View File
@@ -1,6 +1,6 @@
# kenaito-media-picker
媒体文件自动分类整理工具:一键扫描目录下的图片 / 视频 / 音频,按 **方向(横屏 / 竖屏 / 等比)+ 分辨率 + 明暗** 自动归入对应子目录,并提供 Web 管理界面(实时进度、运行日志、媒体库、统计看板、可选色情识别)。
媒体文件自动分类整理工具:一键扫描目录下的图片 / 视频 / 音频,按 **方向(横屏 / 竖屏 / 等比)+ 分辨率 + 明暗** 自动归入对应子目录,并提供 Web 管理界面(实时进度、运行日志、媒体库、统计看板、可选色情识别、可选二次元识别)。
## 功能特性
@@ -11,6 +11,7 @@
- **明暗分类**:基于 ITU-R BT.601 亮度公式,在分辨率目录下追加 `dark_N` / `mid` / `bright_N` 子目录(N 取 20/40/60/80/100 共 5 档)
- **EXIF 旋转修正**:带旋转标记的竖拍图自动处理——有 ffmpeg 时物理转正像素,否则至少按显示方向(宽高对调)归类;可在配置中整体关闭
- **色情识别(可选)**:本机 Python + NudeNet 离线鉴黄,命中的图片移入 `图片_敏感_*` 目录并记录检测分,Web 端可逐张预览复核
- **二次元识别(可选)**:本机 Python + wd-tagger 识别二次元/动漫风格图片,输出 safe/questionable/explicit 三级分级,命中的图片移入 `图片_二次元_*` 目录并记录分级标签与 top tags,Web 端可逐张预览复核
- **异常兜底**:读取失败、不支持格式自动归入「读取异常」「已忽略」目录;GIF、PSD 单独归类
- **断点续传**:每个文件归类结果实时写入续传表(`scan_log`),扫描中断/出错后重跑时,已归类过的文件直接复用上次分类,不再重新探测尺寸 / 算 MD5 / 分析明暗 / 色情识别
- **媒体信息入库**:自动把文件 MD5 与完整媒体信息(类型 / 宽高 / 时长 / 编码 / 容器等)写入 `media-info.db`(SQLite),支持筛选查询与去重
@@ -46,6 +47,7 @@ Web 管理界面(默认 http://localhost:8080)。
| 统计看板 | 媒体总数 / 总体积 / 平均·最大·最小文件 / 总时长,以及类型、方向、分辨率、编码、格式、扩展名等分布与体积 TOP10 |
| 媒体库 | 按类型 / 方向 / 分辨率 / 编码 / 格式 / 文件名筛选,分页 + 列排序 |
| 色情识别 | 展示最近一次开启识别扫描命中的图片:检测分 + 完整路径 + 缩略图预览,便于人工复核 |
| 二次元识别 | 展示最近一次开启识别扫描命中的二次元图片:分级(safe/questionable/explicit)+ 检测分 + top 标签 + 完整路径 + 缩略图预览,便于人工复核 |
## 配置(application.properties)
@@ -62,6 +64,9 @@ Web 管理界面(默认 http://localhost:8080)。
| `nsfw.enabled` | `false` | 是否开启色情图片识别 |
| `nsfw.python` | 空 | python 可执行文件路径;留空自动在 PATH 找 |
| `nsfw.threshold` | `0.5` | 判定阈值(0~1),敏感部位检测分达到即判为色情 |
| `hentai.enabled` | `false` | 是否开启二次元图片识别 |
| `hentai.python` | 空 | python 可执行文件路径;留空自动在 PATH 找(可与 nsfw.python 相同) |
| `hentai.threshold` | `0.5` | 判定阈值(0~1),questionable 或 explicit 分数达到即判为二次元敏感 |
## 整理规则
@@ -80,6 +85,7 @@ KMP已整理/
├── 图片_PSD/ ← PSD 设计稿原样收走
├── 图片_读取异常/ 图片_已忽略/
├── 图片_敏感_横屏_1080P/bright_20/ ← 判为色情的图片(明暗子目录照常)
├── 图片_二次元_横屏_1080P/bright_20/ ← 判为二次元敏感的图片(明暗子目录照常)
├── 视频_横屏_1080P/ 视频_竖屏_1K/ 视频_等比_原画质/
├── 视频_横屏_GIF/ 视频_竖屏_GIF/ 视频_等比_GIF/
├── 视频_读取异常/ 视频_已忽略/
@@ -121,11 +127,24 @@ lightScore = 亮度 > 175 的像素占比
- **开启**:`application.properties` 设 `nsfw.enabled=true`
- **依赖**:本机安装 Python 并 `pip install nudenet`
- **模型**:优先加载程序运行目录下 `lib/320n.onnx`(本仓库已附带,约 11.6MB,离线可用);本地缺失时自动下载到该位置,下载失败再回退用 nudenet 包自带模型
- **模型**:优先加载程序运行目录下 `lib/nwfs/320n.onnx`(本仓库已附带,约 11.6MB,离线可用);本地缺失时自动下载到该位置,下载失败再回退用 nudenet 包自带模型
- **可调**:`nsfw.python`(python 路径)、`nsfw.threshold`(判定阈值)
- **敏感类**:`FEMALE_GENITALIA_EXPOSED` / `MALE_GENITALIA_EXPOSED` / `ANUS_EXPOSED` / `FEMALE_BREAST_EXPOSED`,任一分数达标即判定
- **降级**:未装 python / nudenet 时打印警告并跳过识别,图片按普通流程整理,不影响其它功能
### 二次元图片识别(可选)
基于本机 **Python + wd-tagger**(SmilingWolf/wd-vit-large-tagger-v3)的二次元图片分级识别,专门针对动漫/二次元风格训练,对 R15/R18 擦边图识别效果优于 NudeNet。判为敏感(questionable/explicit)的图片移入 `图片_二次元_*` 分类目录(明暗子目录照常保留),并可在 Web「二次元识别」页面查看每张图的分级、检测分、top 标签、路径与预览。
- **开启**:`application.properties` 设 `hentai.enabled=true`
- **依赖**:本机安装 Python 并 `pip install onnxruntime Pillow numpy`
- **模型**:首次启动自动从 HuggingFace 下载到 `lib/wd-tagger/`(约 1.5GB,需联网);下载完成后离线可用
- **可调**:`hentai.python`(python 路径)、`hentai.threshold`(判定阈值)
- **分级输出**:`rating:safe` / `rating:questionable` / `rating:explicit`,questionable 或 explicit 分数达到阈值即判定为敏感
- **标签输出**:同时输出 top 10 高置信度标签(如 `1girl`, `solo`, `long_hair` 等),便于人工复核
- **降级**:未装 python / 依赖或模型下载失败时打印警告并跳过识别,图片按普通流程整理,不影响其它功能
- **与色情识别的关系**:两者独立运行,可同时启用;同一张图优先走色情识别(nsfw > hentai > normal)
## 构建编译
```shell
@@ -167,8 +186,13 @@ Remove-Item Env:CGO_ENABLED,Env:GOOS,Env:GOARCH
sudo yum install -y python3
pip3 install nudenet
```
模型文件 `lib/320n.onnx` 需与二进制放在同一目录(没有会自动下载)。
3. 其余步骤与 Windows 一致:`application.properties`、`media-info.db` 随运行目录自动创建。
模型文件 `lib/nwfs/320n.onnx` 需与二进制放在同一目录(没有会自动下载)。
3. **二次元识别(可选)**:Linux 上同样要装 Python 与依赖,并在 `application.properties` 里配 `hentai.python`(如 `/usr/bin/python3`):
```shell
pip3 install onnxruntime Pillow numpy
```
模型文件首次启动会自动从 HuggingFace 下载到 `lib/wd-tagger/`(约 1.5GB,需联网)。
4. 其余步骤与 Windows 一致:`application.properties`、`media-info.db` 随运行目录自动创建。
### 前端开发模式(无需重复构建)
@@ -188,7 +212,8 @@ npm install && npm run dev
```text
├── main.go # 程序入口(Gin + 内嵌前端产物)
├── application.properties # 运行配置(端口 / 数据库 / 旋转开关 / 色情识别)
├── lib/320n.onnx # 色情识别模型(随仓库分发,离线可用)
├── lib/nwfs/320n.onnx # 色情识别模型(随仓库分发,离线可用)
├── lib/wd-tagger/ # 二次元识别模型(首次启动自动下载,约 1.5GB)
├── build.sh # 编译脚本
├── internal/
│ ├── scanner/ # 文件扫描、MIME 读取、候选过滤
@@ -196,10 +221,11 @@ npm install && npm run dev
│ ├── classify/ # 纯函数归类规则(方向 + 标准分辨率 + K档 + 明暗等级)
│ ├── organize/ # 整理编排:探测 → 归类 → 收集 → 移动 → 入库
│ ├── mover/ # 文件移动(rename / 跨盘 copy+delete)
│ ├── store/ # SQLite 媒体信息 / 色情记录持久化 + 查询/统计
│ ├── store/ # SQLite 媒体信息 / 色情记录 / 二次元记录持久化 + 查询/统计
│ ├── service/ # 后台任务编排(扫描整理任务 + 状态/日志/WebSocket)
│ ├── nsfw/ # 色情图片识别(内嵌 python 服务 + NudeNet 本地 HTTP)
│ ├── api/ # HTTP 接口层(扫描 / 媒体库 / 统计 / 色情识别 / 目录浏览)
│ ├── hentai/ # 二次元图片识别(内嵌 python 服务 + wd-tagger 本地 HTTP)
│ ├── api/ # HTTP 接口层(扫描 / 媒体库 / 统计 / 色情识别 / 二次元识别 / 目录浏览)
│ └── digest/ # 文件 MD5 / 指纹采样
└── frontend/ # 前端工程(Vue 2 + ElementUI + Vite)
```