Enhance documentation and UI for HVideoTool: added restoration feature for detected regions, updated layout for collection controls, and improved navigation bar. Clarified tool capabilities and limitations in README and CLAUDE.md.
This commit is contained in:
@@ -38,14 +38,19 @@ a detector, draws the regions, and shows a detailed per-image list of what it fo
|
||||
|
||||
Keep this scope sharp:
|
||||
|
||||
- It is a **detection + overlay/inspection** tool. It does **not** remove, restore, or
|
||||
reconstruct censored content.
|
||||
- It does **not** generate images. There is **no** ControlNet / SDXL / diffusion
|
||||
pipeline. (`xinsir/controlnet-union-sdxl-1.0` was considered early but rejected — a
|
||||
generative model, not a detector. Do not reintroduce it.)
|
||||
- Primary job is **detection + overlay/inspection**. A **restoration** ("расцензурить")
|
||||
step was added later (user-requested): per-frame, on-demand, behind a `Restorer`
|
||||
interface. The shipped engine is a cv2 **inpaint baseline** (fills, does NOT truly
|
||||
reconstruct); a generative engine (DeepMosaics / LADA BasicVSR++) is the intended
|
||||
real engine but needs weights + a CUDA GPU and is not wired yet.
|
||||
- Still **no diffusion / ControlNet / SDXL**. (`xinsir/controlnet-union-sdxl-1.0` was
|
||||
rejected early — a generative *conditioning* model, not a censorship restorer. Don't
|
||||
reintroduce it.) Restoration, if upgraded, uses a mosaic-removal model (DeepMosaics/
|
||||
LADA), not a general text-to-image diffusion pipeline.
|
||||
- It detects **already-censored** regions, not "content that should be censored"
|
||||
(i.e. not an NSFW classifier).
|
||||
- It does **not** decode video. No PyAV. Input is image files only.
|
||||
- Video is only a one-shot frame-extraction convenience (see below); detection and
|
||||
restoration operate on image folders.
|
||||
|
||||
## Target environment
|
||||
|
||||
@@ -91,6 +96,11 @@ hvideotool/
|
||||
├── video/
|
||||
│ ├── extract.py # extract_frames(): ffmpeg CLI (cv2 fallback) -> JPGs; keyframe/step modes + downscale
|
||||
│ └── frame.py # Frame dataclass (image BGR, index, pts) — the detector input type
|
||||
├── restore/ # "un-censor" detected regions (per-frame)
|
||||
│ ├── base.py # Restorer ABC: restore(image, detections) -> image
|
||||
│ ├── factory.py # build_restorer(name) -> inpaint (deepmosaics/lada = not wired yet)
|
||||
│ ├── inpaint.py # InpaintRestorer (cv2) — baseline, fills not reconstructs
|
||||
│ └── mask.py # detections_to_mask(shape, dets, dilate)
|
||||
└── detection/
|
||||
├── base.py # Detector ABC: detect(frame) -> list[Detection]
|
||||
├── factory.py # build_detector(config) -> classic | yolo | combined
|
||||
@@ -115,12 +125,32 @@ hvideotool/
|
||||
"Детектировать все" (whole folder, progress bar). Do NOT re-add auto-detect-on-select.
|
||||
Results cache in `_results`; the file-list row gets a count suffix when computed.
|
||||
Switching detector/model clears the cache (`_invalidate_results`).
|
||||
- **Collections (curation).** "Создать коллекцию…" makes a destination folder
|
||||
(`_collections_base()` = the opened folder's parent, else `~/HVideoTool/collections`)
|
||||
and marks it active. The file list is `ExtendedSelection`; "В коллекцию" / Ctrl+M
|
||||
**moves** (`shutil.move`, not copy) the selected frames there, removing them from the
|
||||
- **Collections (curation).** A combo in the left pane (next to the file list, since it
|
||||
acts on the list selection — not on the toolbar, to keep that uncluttered)
|
||||
(`collection_combo`) picks the active destination; `_refresh_collections()` repopulates it from sibling folders of the
|
||||
opened folder (`_collections_base()` = the opened folder's parent, else
|
||||
`~/HVideoTool/collections`) on load/create, so previously-made collections are
|
||||
reselectable. Items carry the path in itemData; "— не выбрана —" = None,
|
||||
"Выбрать папку…" = `"__browse__"` sentinel → `_browse_collection()` for an arbitrary
|
||||
folder (kept in the combo even if outside base). "Создать…" makes a new one and
|
||||
selects it. The file list is `ExtendedSelection`; "В коллекцию" / Ctrl+M **moves**
|
||||
(`shutil.move`, not copy) the selected frames there, removing them from
|
||||
list/`_files`/cache. `_unique_dest` avoids clobbering (`foo.jpg` → `foo (1).jpg`).
|
||||
Use case: sort frames into a training/example set while inspecting detections.
|
||||
- **Restoration ("Расцензурить кадр").** Toolbar action runs `self._restorer` (built via
|
||||
`build_restorer`) on the current frame's detections (computing them first if needed),
|
||||
caches the result in `_restored[path]`, and shows it overlay-free. "Показать оригинал/
|
||||
результат" toggles (`_showing_restored`); "Сохранить результат" writes
|
||||
`<stem>_restored.jpg` into the active collection (or beside the frame). The baseline
|
||||
is cv2 inpaint — honest: it fills, doesn't reconstruct. To add a real engine,
|
||||
implement `core/restore/base.Restorer`, register it in `restore/factory.build_restorer`,
|
||||
and swap `self._restorer`. `_show` resets `_showing_restored` + `_update_restore_actions`.
|
||||
- **Navigation bar** under the image (`_build_nav_bar`): prev/next frame (◀ ▶, keys
|
||||
`,`/`.`), a scrubber `frame_slider` across the whole sequence, a `pos_label`
|
||||
("row / n"), and jump-to-detection (◀ детекция / детекция ▶, keys `[`/`]`,
|
||||
`_step_hit` scans `_results` for the next non-empty frame). The slider and file list
|
||||
are kept in sync via `_update_nav` guarded by `_nav_sync` (avoids signal loops); all
|
||||
navigation ultimately drives `file_list.setCurrentRow`.
|
||||
- `image_view.ImageView` draws the image scaled-to-fit plus overlays. Overlay
|
||||
visibility/threshold are applied at paint time. Selecting a row in the detail table
|
||||
calls `set_highlight(i)` — that detection is drawn boldly (even below threshold) and
|
||||
|
||||
Reference in New Issue
Block a user