File size: 2,017 Bytes
bb75e0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"""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"]