Enhance HVideoTool with background processing and device detection: implemented a background job system for detection and restoration tasks, updated the UI to display CUDA/CPU status, and improved device diagnostics. Documentation in README and CLAUDE.md reflects these changes.

This commit is contained in:
Leonid Pershin
2026-06-07 05:24:06 +03:00
parent e27dfdf518
commit cc518cc3e6
7 changed files with 497 additions and 129 deletions
+12 -7
View File
@@ -54,15 +54,20 @@ class YoloDetector(Detector):
"(и PyTorch с CUDA отдельно — см. README)."
) from exc
# Resolve the device: explicit override, else CUDA when available.
# Resolve the device: CUDA only when actually available, else CPU. A CPU-only
# torch build raises "Torch not compiled with CUDA enabled" if asked for cuda,
# so we never request it without a working GPU (even on an explicit override).
try:
import torch
cuda_ok = torch.cuda.is_available()
except Exception: # noqa: BLE001
cuda_ok = False
device = self.cfg.yolo_device
if device is None:
try:
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
except Exception: # noqa: BLE001
device = "cpu"
device = "cuda" if cuda_ok else "cpu"
elif "cuda" in str(device) and not cuda_ok:
device = "cpu"
self._device = device
self._model = YOLO(model_path)
+8
View File
@@ -118,6 +118,14 @@ class DeepMosaicsRestorer(Restorer):
return
if str(_VENDOR) not in sys.path:
sys.path.insert(0, str(_VENDOR)) # so vendored `from models/util import …` resolve
# Fall back to CPU when CUDA isn't available: DeepMosaics calls `.cuda()`
# whenever gpu_id != "-1", which raises "Torch not compiled with CUDA enabled"
# on a CPU-only torch build.
import torch # noqa: E402
if self._gpu != "-1" and not torch.cuda.is_available():
self._gpu = "-1"
from models import loadmodel, runmodel # type: ignore # noqa: E402
import util.image_processing as impro # type: ignore # noqa: E402
+80
View File
@@ -0,0 +1,80 @@
"""Probe the PyTorch / CUDA situation, so the UI can show a device badge.
Pure (no Qt). ``gather()`` imports torch (slow / heavy) — call it off the GUI
thread. The rest are tiny formatters the UI uses to explain *why* it's on CPU and
how to enable the GPU.
"""
from __future__ import annotations
# pip index for the CUDA build (matches the README).
CUDA_WHEEL_INDEX = "https://download.pytorch.org/whl/cu121"
def gather() -> dict:
"""Collect torch/CUDA facts. Never raises — missing torch is a valid result."""
info: dict = {
"installed": False,
"version": None, # torch.__version__ (e.g. "2.12.0+cpu")
"built_cuda": None, # torch.version.cuda (None on a CPU-only build)
"cuda_available": False,
"device_name": None, # the active GPU's name, if any
"import_error": None,
}
try:
import torch
except Exception as exc: # noqa: BLE001 - report any import failure, not just ImportError
info["import_error"] = str(exc)
return info
info["installed"] = True
info["version"] = getattr(torch, "__version__", None)
try:
info["built_cuda"] = torch.version.cuda
except Exception: # noqa: BLE001
info["built_cuda"] = None
try:
info["cuda_available"] = bool(torch.cuda.is_available())
except Exception: # noqa: BLE001
info["cuda_available"] = False
if info["cuda_available"]:
try:
info["device_name"] = torch.cuda.get_device_name(0)
except Exception: # noqa: BLE001
info["device_name"] = None
return info
def device_label(info: dict) -> str:
return "CUDA" if info.get("cuda_available") else "CPU"
def reason(info: dict) -> str:
"""One-sentence human explanation of the current device choice."""
if not info.get("installed"):
return ("PyTorch не установлен — детектор YOLO и восстановление DeepMosaics "
"работают на CPU (классический детектор torch не требует).")
if info.get("cuda_available"):
name = info.get("device_name") or "GPU"
return f"PyTorch использует CUDA: {name}. Вычисления идут на видеокарте."
version = info.get("version") or "?"
built = info.get("built_cuda")
if not built:
return (f"Установлена CPU-сборка PyTorch ({version}) — без поддержки CUDA, "
"поэтому вычисления идут на процессоре (медленно).")
return (f"PyTorch собран с CUDA {built} ({version}), но GPU недоступен: нет "
"NVIDIA-видеокарты, не установлен/устарел драйвер, либо версия CUDA "
"несовместима с драйвером.")
def install_hint() -> str:
"""Steps to enable the GPU (shown when running on CPU)."""
return (
"Как включить GPU (NVIDIA):\n"
"1. Нужна видеокарта NVIDIA и свежий драйвер (проверка в консоли: nvidia-smi).\n"
"2. Переустановите PyTorch со сборкой CUDA:\n\n"
" pip uninstall -y torch torchvision\n"
f" pip install torch torchvision --index-url {CUDA_WHEEL_INDEX}\n\n"
"3. Перезапустите приложение.\n\n"
"Классический детектор работает и без CUDA. На CPU детекция и расцензуривание "
"просто медленнее."
)