csbdeep-app / core /synth.py
katospiegel's picture
Deploy csbdeep-app as an imaging-plaza Gradio Space (SDSC)
1483ffb verified
Raw
History Blame Contribute Delete
1.7 kB
"""Synthesize a clean microscopy-like image and a degraded (blurred + noisy) version."""
from __future__ import annotations
import numpy as np
def clean_image(h: int = 256, w: int = 256, seed: int = 0) -> np.ndarray:
"""A microscopy-style scene: blobs (cells) + filaments, values in [0, 1]."""
rng = np.random.default_rng(seed)
img = np.zeros((h, w), np.float32)
yy, xx = np.mgrid[0:h, 0:w]
for _ in range(35): # blobs
cy, cx = rng.uniform(0, h), rng.uniform(0, w)
r = rng.uniform(3, 9)
img += rng.uniform(0.4, 1.0) * np.exp(-(((yy - cy) ** 2 + (xx - cx) ** 2) / (2 * r ** 2)))
for _ in range(12): # filaments
y0, x0 = rng.uniform(0, h), rng.uniform(0, w)
ang = rng.uniform(0, np.pi)
for t in np.linspace(0, rng.uniform(20, 60), 200):
y, x = int(y0 + t * np.sin(ang)), int(x0 + t * np.cos(ang))
if 0 <= y < h and 0 <= x < w:
img[max(0, y - 1):y + 1, max(0, x - 1):x + 1] += 0.5
return np.clip(img / max(img.max(), 1e-6), 0, 1)
def degrade(clean: np.ndarray, psf_sigma: float = 2.0, peak: float = 40.0,
read_sigma: float = 0.03, seed: int = 1) -> np.ndarray:
"""Blur with a Gaussian PSF, then add Poisson (shot) + Gaussian (read) noise."""
from scipy.ndimage import gaussian_filter
rng = np.random.default_rng(seed)
blurred = gaussian_filter(clean, sigma=psf_sigma)
shot = rng.poisson(np.clip(blurred, 0, None) * peak) / peak # photon noise
noisy = shot + rng.normal(0, read_sigma, clean.shape) # read noise
return np.clip(noisy, 0, 1).astype(np.float32)