Refactor HVideoTool to exclusively use YOLO for detection and DeepMosaics for restoration: removed classic CV and composite detectors, updated configuration and UI accordingly. Enhanced documentation in README and CLAUDE.md to reflect these changes, including new batch processing capabilities and device diagnostics.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
"""Restorer interface — "un-censor" detected regions of an image.
|
||||
|
||||
A Restorer takes an image plus the detected censored regions and returns a new
|
||||
image with those regions reconstructed/filled. This mirrors the ``Detector``
|
||||
abstraction so different engines (classic inpaint now; a generative model like
|
||||
DeepMosaics / LADA later) plug in behind the same interface.
|
||||
image with those regions reconstructed. This mirrors the ``Detector`` abstraction
|
||||
so different DeepMosaics engines (per-frame and temporal/BVDNet; LADA later) plug
|
||||
in behind the same interface. Note DeepMosaics locates the mosaic itself, so the
|
||||
``detections`` argument is currently advisory (unused by the DeepMosaics engines).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -24,7 +25,18 @@ class Cancelled(Exception):
|
||||
"""Raised by a Restorer when ``should_cancel`` asked it to stop."""
|
||||
|
||||
|
||||
# Sequence (batch) restore callbacks — see ``Restorer.restore_sequence``.
|
||||
FrameGetter = Callable[[int], np.ndarray] # index -> BGR image
|
||||
DetGetter = Callable[[int], list[Detection]] # index -> that frame's detections
|
||||
ResultSink = Callable[[int, np.ndarray], None] # (index, restored image) -> None
|
||||
|
||||
|
||||
class Restorer(ABC):
|
||||
#: Whether this engine uses *neighbouring* frames (so a batch run must feed it a
|
||||
#: contiguous, ordered sequence — see :meth:`restore_sequence`). Per-frame engines
|
||||
#: leave this False; the temporal DeepMosaics (BVDNet) sets it True.
|
||||
temporal: bool = False
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return type(self).__name__
|
||||
@@ -42,3 +54,24 @@ class Restorer(ABC):
|
||||
True the engine should abort and raise :class:`Cancelled`.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def restore_sequence(
|
||||
self,
|
||||
count: int,
|
||||
get_frame: FrameGetter,
|
||||
get_dets: DetGetter,
|
||||
emit: ResultSink,
|
||||
should_cancel: CancelCheck | None = None,
|
||||
) -> None:
|
||||
"""Restore ``count`` frames *in order*, calling ``emit(i, restored)`` for each.
|
||||
|
||||
The default treats every frame independently (just loops :meth:`restore`).
|
||||
Temporal engines override this to pull neighbouring frames via ``get_frame``
|
||||
and carry recurrent state across the sequence. ``get_frame``/``get_dets`` are
|
||||
lazy so the engine only reads the frames it needs; ``emit`` lets the caller
|
||||
stream results to disk instead of holding them all in memory.
|
||||
"""
|
||||
for i in range(count):
|
||||
if should_cancel is not None and should_cancel():
|
||||
raise Cancelled("Восстановление отменено")
|
||||
emit(i, self.restore(get_frame(i), get_dets(i), should_cancel))
|
||||
|
||||
Reference in New Issue
Block a user