# 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). Уже посчитанное при отмене сохраняется в кэш. - **Навигация под картинкой**: ◀ ▶ (`,`/`.`), ползунок-перемотка и переходы к кадрам с детекцией ◀/▶ (`[`/`]`). На ползунке **бирюзовыми метками** отмечены кадры с найденной цензурой; строки списка **подсвечиваются цветом** (🔴 цензура найдена, 🟢 проверено и чисто). - Переключение **детектора** (`classic` / `yolo` / `combined`) и **порога** уверенности прямо в тулбаре — удобно сравнивать. - Выбор файла весов модели кнопкой **«Модель…»**. ## Кэш детекций Результаты детекции сохраняются в корне проекта в файл `detections.json`. Это даёт: - **возобновление между сессиями** — открыли проект повторно, готовые детекции сразу на месте (метки на ползунке и подсветка строк восстанавливаются); - **дозапуск** — «Детектировать все» пропускает уже посчитанные кадры; - **отказоустойчивость** — при отмене/закрытии посчитанное не теряется. Кэш помечен «удостоверением» детектора (детектор + модель + порог `conf`/`imgsz`). Если открыть проект **другим** детектором, чужой кэш не загружается (чтобы не выдавать старые результаты за текущие). Полностью пересчитать — кнопка **«Все заново»**. > Ключи внутри файла — **имена файлов**, поэтому кэш переживает перемещение/ > переименование проекта. Хранится результат **одного** детектора за раз: посчитали > одним, переключились на другой и посчитали — кэш перезапишется. ## Восстановление (расцензуривание) Кнопка **«Расцензурить кадр»** восстанавливает найденные области на текущем кадре, **«Показать оригинал/результат»** переключает вид, **«Сохранить результат»** пишет `<имя>_restored.jpg` рядом с кадром. Движок выбирается в меню **Файл → Движок восстановления…**. Два движка: - **Инпейнт (cv2)** — по умолчанию, без модели и GPU. ⚠️ *Заполняет* область по окружению, но **не реконструирует** скрытые детали (замазывает, а не раскрывает). - **DeepMosaics** — реальное генеративное удаление мозаики. Код **встроен** в приложение (vendored, GPL-3.0), ставить его отдельно не нужно — требуются только **веса** и (желательно) **GPU NVIDIA/CUDA**. На аниме качество ограничено (модели обучены на реальном видео). ### Настройка DeepMosaics Нужны только **веса** — положите их в **`models/deepmosaics/`** (папка в `.gitignore`, веса большие, ~92 МБ). Скачать: официальная папка ([Google Drive](https://drive.google.com/drive/folders/1LTERcN33McoiztYEwBxMuRjjgxh4DEPs), Baidu код `1x0a`): - **`clean_youknow_resnet_9blocks.pth`** — картиночная clean-модель; - **`mosaic_position.pth`** — локатор мозаики (должен лежать рядом). Затем в приложении: **Файл → Движок восстановления… → DeepMosaics**, выберите **модель из выпадающего списка** (наполняется из `models/deepmosaics`; есть «Обзор…» для файла в другом месте) и GPU id (`-1` = CPU). Если веса в `models/deepmosaics` — работает сразу; модель грузится один раз, дальше кадры считаются быстро. > **Важно:** берите именно **картиночную** модель `clean_youknow_resnet_9blocks.pth`. > Видеомодель `clean_youknow_video.pth` (BVDNet) покадрово **не работает** — ей нужен > соседний кадр (приложение это распознаёт и подскажет). Если на кадре нет мозаики, > результат = исходный кадр. > > Код DeepMosaics (GPL-3.0) лежит в `core/restore/_deepmosaics/` и поэтому **весь > проект распространяется под GPL-3.0**. Запускается на современных `torch 2.x`/ > `numpy 2.x` (проверено). [LADA](https://github.com/ladaapp/lada) (видеомодель, > лучшее качество на реальном видео) пока не подключён. ## Что НЕ делает (осознанно вне области задачи) - Не **генерирует** изображения через диффузию (никакого ControlNet/SDXL). - Не детектирует «контент, который следовало бы зацензурить» (NSFW) — ищем именно **уже наложенную** цензуру. - Полноценное генеративное восстановление пока не подключено (см. выше). --- ## Требования - **ОС:** Windows 11 x64 (основная целевая платформа). - **Python:** 3.11+. - **GPU (опционально):** NVIDIA + CUDA для YOLO-детектора. CPU-режим работает, но медленный. Для `classic` детектора ни torch, ни GPU не нужны. ## Установка ```powershell git clone https://github.com/mrleo1nid/HVideoTool.git cd HVideoTool python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -e . ``` Этого достаточно для `classic` детектора — **PyTorch/CUDA не требуются**. Они нужны только для YOLO/комбинированного детектора (см. [Модель детектора](#модель-детектора)). ## Запуск ```powershell # Без аргументов — открывается последний проект (или создайте/откройте новый в тулбаре) python -m hvideotool # Необязательно: сразу открыть проект / переопределить детектор и модель (по умолчанию) python -m hvideotool "C:\path\to\МойПроект" --detector yolo --model models\lada_mosaic_detection_model_v4_accurate.pt ``` Выбор детектора, путь к модели и порог сохраняются в `~/HVideoTool/settings.json` и применяются при следующем запуске. --- ## Модель детектора Интерфейс детектора абстрагирован (`core/detection/base.py`), детектор выбирается в тулбаре (или флагом `--detector`): - `classic` — эвристический classic-CV детектор (`core/detection/classic_cv.py`). Различает `mosaic` / `blur` / `black_bar`, без весов и без GPU. **Приблизительный**: на реальном видео даёт много ложных срабатываний, заточен скорее под рисованный/аниме контент — но и там ненадёжен. - `yolo` — ML-детектор на базе [Ultralytics](https://github.com/ultralytics/ultralytics) (`core/detection/yolo.py`). **Сегментационная** модель — маски превращаются в контуры. Рекомендуемые веса — [**LADA mosaic detection**](https://huggingface.co/ladaapp/lada). - `combined` — `CompositeDetector`: YOLO (мозаика) + classic-CV (плашки/размытие), результаты объединяются с дедупликацией по IoU. > **⚠️ Берите правильную модель.** Для YOLO нужна модель **детекции цензуры** > (LADA `lada_mosaic_detection_model_v4_accurate.pt`). Если по ошибке указать > обычную COCO-модель (`yolo11n-seg.pt`), она будет детектить людей/предметы и > помечать их как `unknown` — это и есть «шум». Файл LADA лежит в `models/`. > **Домен важен.** Модель 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 # затем: тулбар → Детектор yolo → «Модель…» → runs\segment\mosaic\weights\best.pt ``` Установка YOLO-детектора: ```powershell pip install -e ".[yolo]" pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 curl.exe -L -o models\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 --detector yolo --model models\lada_mosaic_detection_model_v4_accurate.pt ``` > **⚠️ Лицензия.** Ultralytics YOLO и веса LADA — **AGPL-3.0**. Classic-CV детектор > от этого свободен. --- ## Архитектура (кратко) ``` hvideotool/ ├── __main__.py # точка входа + CLI (всё опционально) ├── app.py # инициализация QApplication ├── config.py # настройки: пороги детекции, оверлей, детектор/модель ├── 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 + индекс + pts) — вход детектора └── detection/ ├── base.py # Detector (ABC): detect(frame) -> list[Detection] ├── factory.py # build_detector(config) -> classic/yolo/combined ├── types.py # Detection (+ to_dict/from_dict), CensorType ├── cache.py # сохранение/загрузка кэша детекций (detections.json в проекте) ├── classic_cv.py # эвристический детектор (mosaic/blur/black_bar) ├── yolo.py # YOLO-детектор (Ultralytics, маски→полигоны) └── composite.py # CompositeDetector: объединение детекторов ``` Детекция синхронная (по клику/по кнопке «Детектировать все»); тяжёлый YOLO на CPU заметно медленнее, чем на CUDA. Длинные операции можно прервать кнопкой «■ Стоп» (Esc), а результаты кэшируются на диск — см. [Кэш детекций](#кэш-детекций). ## Технологический стек | Компонент | Выбор | |----------------------|--------------------------------------------------| | Язык | Python ≥ 3.11 | | GUI | PySide6 (Qt 6) | | Обработка картинок | OpenCV / NumPy | | Детектор (без весов) | classic-CV эвристика (без GPU) | | Детектор (ML) | Ultralytics YOLO + PyTorch/CUDA (LADA) | ## Лицензия TBD.