333 lines
27 KiB
Markdown
333 lines
27 KiB
Markdown
# HVideoTool
|
||
|
||
Десктопная утилита с графическим интерфейсом для **обнаружения уже наложенной
|
||
цензуры** (мозаика, пикселизация, размытие, чёрные плашки) на **картинках**.
|
||
Работа организована в **проекты**: создаёте проект (или раскадровываете ролик кнопкой
|
||
«Создать из ролика…») — приложение прогоняет каждый кадр через детектор, **обводит
|
||
найденные области** и показывает **подробный список** того, что нашлось на каждой
|
||
картинке. Отобранные кадры можно перемещать в **избранное** (для сбора датасета/
|
||
примеров).
|
||
|
||
### Проект
|
||
|
||
Проект — это папка со всем необходимым:
|
||
|
||
```
|
||
МойПроект/
|
||
├── project.json # настройки проекта (детектор, модель, порог, движок) + метаданные
|
||
├── frames/ # картинки проекта
|
||
├── detections.json # кэш детекций
|
||
└── collections/ # коллекции; «Избранное» — папка для отобранных кадров
|
||
```
|
||
|
||
Настройки (детектор / модель / порог / движок восстановления) хранятся **внутри
|
||
проекта** — каждый проект помнит, как его настраивали. Глобальные настройки
|
||
(`~/HVideoTool/settings.json`) задают лишь **значения по умолчанию для новых проектов**
|
||
и список недавних. При запуске без аргументов автоматически открывается последний
|
||
проект.
|
||
|
||
> Инструмент для просмотра, отладки детекции и отбора кадров. Видео раскадровывает
|
||
> через ffmpeg (ставится автоматически с пакетом `imageio-ffmpeg`; системный ffmpeg
|
||
> из PATH используется в приоритете), либо через OpenCV.
|
||
|
||
---
|
||
|
||
## Возможности
|
||
|
||
- **Проекты**: «Создать проект…», «Открыть проект…», «Импортировать папку как
|
||
проект…» (копирует картинки из обычной папки в `frames/` нового проекта) и подменю
|
||
**«Недавние проекты»**.
|
||
- **Создать из ролика…** — раскадровка видео в новый проект (кадры в `frames/`). Два
|
||
режима: **только ключевые кадры** (в разы быстрее — декодируются лишь I-кадры) и
|
||
**каждый N-й кадр**; опциональный даунскейл (меньше файлов и нагрузки на диск/АВ).
|
||
ffmpeg идёт в комплекте (`imageio-ffmpeg`); системный ffmpeg из PATH — в приоритете.
|
||
- **Избранное**: «★ В избранное» (Ctrl+M) перемещает выбранные кадры в папку
|
||
`collections/Избранное` внутри проекта — для отбора кадров (мультивыбор
|
||
поддерживается). Папка создаётся автоматически.
|
||
- Картинки проекта (`.jpg/.png/.bmp/.webp/.tif`) — список слева.
|
||
- Картинка с **обводкой контуром** найденных областей — по центру.
|
||
- **Подробная таблица детекций** справа: тип, уверенность, bbox, число точек
|
||
полигона. Выбор строки **подсвечивает** конкретную область на картинке.
|
||
- **Ленивая детекция**: картинка прогоняется по двойному клику / кнопке «Рассчитать
|
||
кадр», результат кэшируется.
|
||
- **Кэш детекций сохраняется в проект** (см. [ниже](#кэш-детекций)) — при повторном
|
||
открытии проекта результаты подхватываются, не нужно считать заново.
|
||
- **Три режима пересчёта**:
|
||
- **«Детектировать все»** — *дозапуск*: считает только ещё не посчитанные кадры
|
||
(можно прерывать и продолжать);
|
||
- **«Все заново»** — полная регенерация: очищает кэш и пересчитывает весь проект;
|
||
- **«Рассчитать кадр»** (Space / двойной клик) — всегда пересчитывает текущий кадр.
|
||
- **Кнопка «■ Стоп» (Esc)** отменяет любую текущую длинную операцию (детекция всего
|
||
проекта, раскадровка ролика, импорт папки, восстановление DeepMosaics). Уже
|
||
посчитанное при отмене сохраняется в кэш.
|
||
- **Навигация под картинкой**: ◀ ▶ (`,`/`.`), ползунок-перемотка и переходы к
|
||
кадрам с детекцией ◀/▶ (`[`/`]`). На ползунке **бирюзовыми метками** отмечены кадры
|
||
с найденной цензурой; строки списка **подсвечиваются цветом** (🔴 цензура найдена,
|
||
🟢 проверено и чисто).
|
||
- Детекция — через **YOLO**, **несколько моделей сразу** (как ADetailer): сложите веса
|
||
в `models/yolo/<категория>/` (например `models/yolo/mosaic/`, `models/yolo/face/`) и
|
||
отметьте нужные галочками в меню **«Модели»** тулбара. При расчёте кадра прогоняются
|
||
все выбранные модели, их детекции попадают в общую таблицу и рисуются оверлеем —
|
||
**цвет по категории-папке**. Порог уверенности — в тулбаре.
|
||
- **Индикатор устройства** в строке состояния: «⚡ CUDA» или «🖥 CPU». Клик по «CPU»
|
||
показывает диагностику (почему GPU не задействован) и команды установки PyTorch с
|
||
CUDA. Если CUDA недоступна, YOLO и DeepMosaics автоматически работают на CPU
|
||
(медленнее, но без ошибок).
|
||
|
||
## Кэш детекций
|
||
|
||
Результаты детекции сохраняются в корне проекта в файл `detections.json`. Это даёт:
|
||
|
||
- **возобновление между сессиями** — открыли проект повторно, готовые детекции сразу
|
||
на месте (метки на ползунке и подсветка строк восстанавливаются);
|
||
- **дозапуск** — «Детектировать все» пропускает уже посчитанные кадры;
|
||
- **отказоустойчивость** — при отмене/закрытии посчитанное не теряется.
|
||
|
||
Кэш помечен «удостоверением» — **набором выбранных моделей** + `conf`/`imgsz`. Если
|
||
открыть проект с **другим набором моделей**, чужой кэш не загружается (чтобы не выдавать
|
||
старые результаты за текущие). Полностью пересчитать — кнопка **«Все заново»**.
|
||
|
||
> Ключи внутри файла — **имена файлов**, поэтому кэш переживает перемещение/
|
||
> переименование проекта. Хранится результат **одного** детектора за раз: посчитали
|
||
> одним, переключились на другой и посчитали — кэш перезапишется.
|
||
|
||
## Восстановление (расцензуривание)
|
||
|
||
Кнопка **«Расцензурить кадр»** восстанавливает найденные области на текущем кадре,
|
||
**«Показать оригинал/результат»** переключает вид, **«Сохранить результат»** пишет
|
||
`<имя>_restored.jpg` рядом с кадром. Движок выбирается в
|
||
меню **Файл → Движок восстановления…**.
|
||
|
||
**Пакетный прогон по диапазону.** Кнопки **«Расцензурить все»** (дозапуск — пропускает
|
||
уже сделанные) и **«Все заново»** обрабатывают **все кадры проекта** в фоне и пишут
|
||
результаты в папку **`restored/`** проекта (имена кадров сохраняются; папка держится
|
||
отдельно от `frames/`, чтобы результаты не попадали обратно в список кадров). Прогресс,
|
||
отмена (**«■ Стоп»**) и предпросмотр текущего кадра работают как при детекции.
|
||
|
||
Доступны два **семейства** движков: **DeepMosaics** (восстанавливает мозаику) и
|
||
**diffusion-inpaint (SwarmUI)** (перерисовывает область заново). DeepMosaics — по
|
||
умолчанию; код **встроен** (vendored, GPL-3.0; ставить отдельно не нужно — нужны только
|
||
**веса** и желательно **GPU NVIDIA/CUDA**). Три движка в списке:
|
||
|
||
- **DeepMosaics — картинка** — реальное генеративное удаление мозаики **покадрово**.
|
||
- **DeepMosaics — видео (BVDNet)** — **временно́й** движок: использует **соседние кадры**
|
||
(окно ±2 кадра с шагом 3) и собственный предыдущий результат для когерентности на
|
||
роликах. Из-за рекуррентности обрабатывает **непрерывный диапазон по порядку** — т.е.
|
||
запускайте его через **«Расцензурить все»** (одиночный «Расцензурить кадр» сведётся к
|
||
окну из одного кадра). Нужна **видеомодель** `clean_youknow_video.pth`.
|
||
- **Diffusion-inpaint (SwarmUI)** — **перерисовывает** область цензуры заново диффузионной
|
||
inpaint-моделью по **маске из YOLO-детекций** и промпту (не восстанавливает оригинал!).
|
||
Лучше всего для **чёрных плашек / сплошной заливки**, где DeepMosaics бессилен. Покадрово
|
||
→ на роликах будет **мерцание**. См. «Настройка SwarmUI» ниже.
|
||
|
||
На аниме качество DeepMosaics ограничено (модели обучены на реальном видео).
|
||
|
||
### Настройка DeepMosaics
|
||
|
||
Нужны только **веса** — положите их в **`models/deepmosaics/`** (папка в `.gitignore`,
|
||
веса большие, ~92 МБ). Скачать: официальная папка
|
||
([Google Drive](https://drive.google.com/drive/folders/1LTERcN33McoiztYEwBxMuRjjgxh4DEPs),
|
||
Baidu код `1x0a`):
|
||
|
||
- **`clean_youknow_resnet_9blocks.pth`** — картиночная clean-модель (движок «картинка»);
|
||
- **`clean_youknow_video.pth`** — видеомодель BVDNet (движок «видео», соседние кадры);
|
||
- **`mosaic_position.pth`** — локатор мозаики (должен лежать рядом, нужен обоим).
|
||
|
||
Затем в приложении: **Файл → Движок восстановления…**, выберите движок (**DeepMosaics —
|
||
картинка** или **видео**) и **модель из выпадающего списка** (наполняется из
|
||
`models/deepmosaics` — для видеодвижка показываются только `clean_*_video.pth`; есть
|
||
«Обзор…» для файла в другом месте) и GPU id (`-1` = CPU). Если веса в `models/deepmosaics`
|
||
— работает сразу; модель грузится один раз, дальше кадры считаются быстро.
|
||
|
||
> **Какую модель брать:** для покадрового движка — **картиночную**
|
||
> `clean_youknow_resnet_9blocks.pth`; для временно́го — **видео** `clean_youknow_video.pth`
|
||
> (она запускается только пакетно, «Расцензурить все», т.к. ей нужны соседние кадры). Если
|
||
> на кадре нет мозаики, результат = исходный кадр.
|
||
>
|
||
> Код DeepMosaics (GPL-3.0) лежит в `core/restore/_deepmosaics/` и поэтому **весь
|
||
> проект распространяется под GPL-3.0**. Запускается на современных `torch 2.x`/
|
||
> `numpy 2.x` (проверено). [LADA](https://github.com/ladaapp/lada) (видеомодель,
|
||
> лучшее качество на реальном видео) пока не подключён.
|
||
|
||
### Настройка Diffusion-inpaint (SwarmUI)
|
||
|
||
Этот движок перерисовывает область **по маске из детекций YOLO**, поэтому **сначала
|
||
посчитайте детекцию** («Детектировать все» или «Рассчитать кадр»), а затем запускайте
|
||
расцензуривание — кадры без детекций остаются без изменений. Диффузионная модель крутится
|
||
в **отдельном сервере SwarmUI**, приложение лишь шлёт ему по HTTP картинку + маску + промпт
|
||
(никаких `torch`/`diffusers` в самом приложении на этом пути).
|
||
|
||
1. Установите и запустите [SwarmUI](https://github.com/mcmonkeyprojects/SwarmUI), загрузите
|
||
в нём inpaint-чекпойнт (SD/SDXL). По умолчанию сервер слушает `http://localhost:7801`.
|
||
2. В приложении: **Файл → Движок восстановления…** → выберите **Diffusion-inpaint
|
||
(SwarmUI)** и задайте:
|
||
- **SwarmUI URL** (по умолчанию `http://localhost:7801`);
|
||
- **Чекпойнт** — имя модели как её знает SwarmUI (пусто = текущая в сервере);
|
||
- **Промпт / Negative** — что нарисовать в области под цензурой / чего избегать;
|
||
- **Шаги / CFG / Denoise / Seed** — параметры генерации (`Denoise` 0..1, 1 = полностью
|
||
перерисовать; `Seed` `-1` = случайный);
|
||
- **Маска: расширить / размытие** (px) — расширение и мягкость края маски.
|
||
- Кнопка **«Проверить соединение»** дёргает SwarmUI и сразу показывает ✓ (сервер
|
||
отвечает) или ✗ с текстом ошибки — удобно убедиться в адресе до расцензуривания.
|
||
3. Запустите **«Расцензурить кадр»** или **«Расцензурить все»** — движок прогонит только
|
||
кадры с детекциями.
|
||
|
||
> Diffusion **выдумывает** правдоподобное содержимое, а не восстанавливает оригинал. Это
|
||
> сознательно второй движок (не замена DeepMosaics) под случаи, где под цензурой не
|
||
> осталось данных (чёрные плашки). Бэкенд абстрактный — позже можно добавить ComfyUI/A1111
|
||
> как ещё одну реализацию `DiffusionBackend`.
|
||
|
||
## Что НЕ делает (осознанно вне области задачи)
|
||
|
||
- Не **генерирует** изображения через диффузию (никакого ControlNet/SDXL).
|
||
- Не детектирует «контент, который следовало бы зацензурить» (NSFW) — ищем
|
||
именно **уже наложенную** цензуру.
|
||
- Полноценное генеративное восстановление пока не подключено (см. выше).
|
||
|
||
---
|
||
|
||
## Требования
|
||
|
||
- **ОС:** Windows 11 x64 (основная целевая платформа).
|
||
- **Python:** 3.11+.
|
||
- **GPU (опционально):** NVIDIA + CUDA для YOLO-детектора и DeepMosaics. CPU-режим
|
||
работает, но медленный (особенно DeepMosaics / временно́й BVDNet).
|
||
|
||
## Установка
|
||
|
||
```powershell
|
||
git clone https://github.com/mrleo1nid/HVideoTool.git
|
||
cd HVideoTool
|
||
python -m venv .venv
|
||
.\.venv\Scripts\Activate.ps1
|
||
pip install -e ".[yolo]"
|
||
```
|
||
|
||
Детекция (YOLO) и расцензуривание (DeepMosaics) требуют **PyTorch** — установите его
|
||
отдельно под вашу CUDA (см. [Модель детектора](#модель-детектора)).
|
||
|
||
## Запуск
|
||
|
||
```powershell
|
||
# Без аргументов — открывается последний проект (или создайте/откройте новый в тулбаре)
|
||
python -m hvideotool
|
||
|
||
# Необязательно: сразу открыть проект и указать модель YOLO
|
||
python -m hvideotool "C:\path\to\МойПроект" --model models\lada_mosaic_detection_model_v4_accurate.pt
|
||
```
|
||
|
||
Путь к модели и порог сохраняются в `~/HVideoTool/settings.json` и применяются при
|
||
следующем запуске.
|
||
|
||
---
|
||
|
||
## Модели детекции (мульти-YOLO)
|
||
|
||
Детекция — **только YOLO**, но можно держать и включать **несколько моделей сразу**
|
||
(как ADetailer). Структура папок:
|
||
|
||
```
|
||
models/yolo/
|
||
├── mosaic/ # модель(и) детекции мозаики (LADA) — категория "mosaic", красный цвет
|
||
├── face/ # напр. yolov8-face — категория "face", зелёный цвет
|
||
└── <своё>/ # любая категория = имя папки = ярлык + цвет
|
||
```
|
||
|
||
Каждая модель — **сегментационная** YOLO ([Ultralytics](https://github.com/ultralytics/ultralytics),
|
||
`core/detection/yolo.py`), маски превращаются в контуры. Включайте модели галочками в
|
||
меню **«Модели»** тулбара (там же «Добавить модель…» — скопирует `.pt` в нужную
|
||
категорию). При расчёте кадра прогоняются **все включённые** модели, детекции
|
||
объединяются (`core/detection/multi.py`), **цвет и ярлык — по категории-папке**.
|
||
Рекомендуемые веса для мозаики — [**LADA mosaic detection**](https://huggingface.co/ladaapp/lada).
|
||
(Старый эвристический classic-CV детектор и комбинированный режим удалены — давали
|
||
много ложных срабатываний.)
|
||
|
||
> **⚠️ Берите правильную модель для мозаики.** В `models/yolo/mosaic/` нужна модель
|
||
> **детекции цензуры** (LADA `lada_mosaic_detection_model_v4_accurate.pt`). Обычная
|
||
> COCO-модель (`yolo11n-seg.pt`) детектит людей/предметы — это «шум».
|
||
|
||
> **Домен важен.** Модель LADA обучена на **реальном видео** (JAV); на части
|
||
> рисованного/аниме контента работает, на части — плохо. Хорошего публичного
|
||
> YOLO-детектора цензуры для аниме нет — это потребовало бы обучения своей модели.
|
||
|
||
**Своя модель мозаики для аниме.** Можно обучить **YOLO11-seg** на синтетике
|
||
(накладываем мозаику на чистые кадры → авторазметка) и подключить `.pt` в наш
|
||
`YoloDetector` **без изменений кода**. Инструменты — в
|
||
[`scripts/training/`](scripts/training/README.md):
|
||
|
||
```powershell
|
||
python scripts\training\gen_mosaic_dataset.py --input C:\clean_frames --output dataset_mosaic
|
||
python scripts\training\train_mosaic.py --data dataset_mosaic\data.yaml --epochs 100
|
||
# затем скопируйте runs\segment\mosaic\weights\best.pt в models\yolo\mosaic\ и включите галочкой
|
||
```
|
||
|
||
Установка YOLO-детектора:
|
||
|
||
```powershell
|
||
pip install -e ".[yolo]"
|
||
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
|
||
|
||
New-Item -ItemType Directory -Force models\yolo\mosaic | Out-Null
|
||
curl.exe -L -o models\yolo\mosaic\lada_mosaic_detection_model_v4_accurate.pt `
|
||
"https://huggingface.co/ladaapp/lada/resolve/main/lada_mosaic_detection_model_v4_accurate.pt?download=true"
|
||
|
||
python -m hvideotool # модель из models\yolo\mosaic подхватится и включится автоматически
|
||
```
|
||
|
||
> **⚠️ Лицензия.** Ultralytics YOLO и веса LADA — **AGPL-3.0**; код DeepMosaics —
|
||
> **GPL-3.0**. Поэтому весь проект распространяется под **GPL-3.0**.
|
||
|
||
---
|
||
|
||
## Архитектура (кратко)
|
||
|
||
```
|
||
hvideotool/
|
||
├── __main__.py # точка входа + CLI (всё опционально)
|
||
├── app.py # инициализация QApplication
|
||
├── config.py # настройки: порог/оверлей, detector_models (мульти-YOLO), движок восстановления
|
||
├── settings_store.py # дефолты новых проектов + последний/недавние → settings.json
|
||
├── ui/
|
||
│ ├── main_window.py # окно: список файлов | картинка | таблица детекций
|
||
│ ├── image_view.py # отрисовка картинки + оверлей-контуры (QPainter)
|
||
│ └── marker_slider.py # ползунок-перемотка с метками кадров с детекцией
|
||
└── core/
|
||
├── imageio.py # unicode-safe чтение/запись картинок (Windows-пути)
|
||
├── project.py # Project: раскладка (project.json/frames/detections.json/collections) + настройки
|
||
├── video/frame.py # Frame (картинка BGR + индекс) — вход детектора
|
||
├── detection/ # только YOLO, мульти-модель
|
||
│ ├── base.py # Detector (ABC): detect(frame) -> list[Detection]
|
||
│ ├── factory.py # build_detector -> MultiYoloDetector по выбранным моделям
|
||
│ ├── registry.py # поиск моделей в models/yolo/<категория>/*.pt
|
||
│ ├── multi.py # MultiYoloDetector: прогон нескольких моделей + объединение
|
||
│ ├── types.py # Detection (+ label/категория, .display), CensorType
|
||
│ ├── cache.py # кэш детекций (ключ = набор моделей + conf/imgsz)
|
||
│ └── yolo.py # YOLO-детектор (Ultralytics, маски→полигоны, ярлык категории)
|
||
└── restore/ # DeepMosaics (восстановление) или diffusion-inpaint (перерисовка)
|
||
├── base.py # Restorer (ABC): restore() + restore_sequence() + .temporal/.needs_detections
|
||
├── factory.py # build_restorer -> deepmosaics | deepmosaics_video | diffusion
|
||
├── deepmosaics.py # движки «картинка» (покадрово) и «видео» (BVDNet)
|
||
├── _deepmosaics/ # встроенный код DeepMosaics (GPL-3.0)
|
||
├── mask.py # маска из детекций (для diffusion inpaint)
|
||
├── diffusion.py # DiffusionRestorer + DiffusionBackend (ABC) + InpaintParams
|
||
└── swarmui.py # бэкенд SwarmUI (HTTP, stdlib urllib — без torch)
|
||
```
|
||
|
||
Детекция синхронная (по клику/по кнопке «Детектировать все»); тяжёлый YOLO на CPU
|
||
заметно медленнее, чем на CUDA. Длинные операции можно прервать кнопкой «■ Стоп»
|
||
(Esc), а результаты кэшируются на диск — см. [Кэш детекций](#кэш-детекций).
|
||
|
||
## Технологический стек
|
||
|
||
| Компонент | Выбор |
|
||
|----------------------|--------------------------------------------------|
|
||
| Язык | Python ≥ 3.11 |
|
||
| GUI | PySide6 (Qt 6) |
|
||
| Обработка картинок | OpenCV / NumPy |
|
||
| Детектор | Ultralytics YOLO, мульти-модель (models/yolo/<кат>) |
|
||
| Расцензуривание | DeepMosaics (встроен) + PyTorch/CUDA, или diffusion-inpaint через SwarmUI (HTTP) |
|
||
|
||
## Лицензия
|
||
|
||
**GPL-3.0** — из-за встроенного кода DeepMosaics (GPL-3.0); веса/код YOLO LADA — AGPL-3.0.
|