noise2void-app / core /processing.py
katospiegel's picture
Deploy noise2void-app as an imaging-plaza Gradio Space (SDSC)
bb75e0a verified
Raw
History Blame Contribute Delete
2.02 kB
"""The ONE entrypoint a tool author edits.
`process(file_url, engine, radius, strength)` runs Noise2Void self-supervised
denoising on a noisy 2D image and returns a noisy/denoised/clean summary plus a
report (PSNR/SSIM when the clean ground-truth sidecar is available).
"""
from __future__ import annotations
import os
import numpy as np
from . import n2v, viz
from .io import load_image_from_any
ENGINES = n2v.ENGINES
def _to_gray01(arr: np.ndarray) -> np.ndarray:
a = np.asarray(arr)
if a.ndim == 3:
a = a[..., :3].mean(-1)
a = a.astype(np.float32)
return np.clip((a - a.min()) / max(a.max() - a.min(), 1e-6), 0, 1)
def simulate_full(image_path, engine: str = "fast", radius: int = 2,
strength: float = 1.0) -> dict:
if engine not in ENGINES:
raise ValueError(f"Unknown engine '{engine}'. Choose one of {ENGINES}.")
noisy = _to_gray01(load_image_from_any(image_path))
clean = None
# Clean ground-truth sidecar, saved next to the baked example as a hidden file
# (leading dot) so it is never mistaken for an input image.
if isinstance(image_path, str):
base = os.path.splitext(image_path)[0]
d, name = os.path.split(base)
for side in (base + "_clean.npy", os.path.join(d, "." + name + "_clean.npy")):
if os.path.exists(side):
try:
clean = np.load(side)
except Exception: # noqa: BLE001
clean = None
break
res = n2v.analyze(noisy, engine=engine, radius=int(radius),
strength=float(strength), clean=clean)
return {"summary": viz.summary_image(res), "report": res["report"], "res": res}
def process(image_path, engine: str = "fast", radius: int = 2,
strength: float = 1.0) -> tuple[np.ndarray, dict]:
"""Returns (noisy/denoised/clean summary RGB, report dict)."""
r = simulate_full(image_path, engine, radius, strength)
return r["summary"], r["report"]