transform op• Datenarten: image2d → image2d
• Aufruf: import fullseye as fs; fs.ledger.anscombe_transform(image, gain=1.0, read_sigma=0.0, offset=0.0, clip=False) (die Implementierung direkt: import photoncount; photoncount.anscombe_transform(image, gain=1.0, read_sigma=0.0, offset=0.0, clip=False); aus dem Register: opsphoton.get("anscombe_transform"))
Anscombe-Varianzstabilisierung: Poisson-Zählungen -> etwa Einheitsvarianz.
> Die ausführliche Beschreibung unten ist der Originaltext — Zusammenfassung und Überschriften sind übersetzt.
Photon-limited data has signal-dependent noise, which every classical denoiser (Gaussian, bilateral, NLM, wavelet, BM3D) assumes away. The Anscombe transform A(x) = 2*sqrt(x + 3/8) makes the variance approximately 1 *independently of the signal*, so the standard route is transform -> denoise with a unit-sigma Gaussian denoiser -> anscombe_inverse.
The generalised form (Starck/Murtagh/Bijaoui) also absorbs the sensor's analogue chain, and takes exactly the parameters backends_aug.aug_read_noise injects::
A(x) = (2/g) * sqrt(g*(x - offset) + (3/8)*g^2 + sigma_r^2)
with *gain* g in ADU per photon, *read_sigma* the Gaussian read noise in ADU and *offset* the black level in ADU. The defaults g=1, sigma_r=0, offset=0 reduce it to the classical form exactly.
Measured stabilisation — var(A(X)) for X ~ Poisson(lambda), computed exactly by summing the Poisson pmf (no sampling, so anyone can reproduce these; tests/test_photoncount.py pins them and the sampled versions):
======== ========
lambda var(A)
======== ========
1 0.717443
2 0.924297
4 0.998754
10 1.000910
100 1.000006
======== ========
So "variance 1" is true from about 4 photons/pixel upward and false below it — at 1 photon/pixel the variance is 0.717, a 28% shortfall, which is the honest statement of the transform's low-count limit. Below a few photons an exact Poisson method (or the exact unbiased inverse, see anscombe_inverse) is required.
It does not help a linear smoother, and the tests say so. Measured on a two-level scene (4 and 64 photons/pixel, seed 5): a plain Gaussian filter applied to the raw counts reaches RMSE 2.387, and the same filter through the Anscombe route reaches 2.459 — i.e. *slightly worse*. That is expected:
averaging is already the right thing to do to Poisson counts, so stabilising the variance first buys nothing. The transform pays off for denoisers whose parameter is an absolute noise scale — thresholds, sigma filters, wavelet shrinkage, NLM, BM3D — because that parameter becomes one constant instead of a per-pixel function. Measured with a 5x5 sigma filter at a 3-sigma threshold on that same scene: 1.191 through the transform against 2.307 in the raw domain using the same 3-sigma rule with a globally estimated sigma. (An *oracle* raw threshold, swept against ground truth one does not have in practice, reaches 1.080 — so the honest headline is "one principled constant instead of a tuned guess", not "always better".)
Returns a float64 array of the same shape as *image*.
Raises ValueError: non-finite *image*, non-positive *gain*, negative *read_sigma*, and — unless clip=True — any pixel whose argument under the square root is negative (which can happen for real read-noise data dipping below the black level). clip=True floors the argument at 0 and is the documented, opt-in behaviour; the default refuses rather than quietly manufacturing a value.
• Leitfaden zur Familie photon_timeresolved
• Katalog der Beispieldaten (Download-URLs / Lizenzen) — 2-D nutzt skimage.data (BSD/Public Domain) plus synthetische Bilder, 3-D nennt Download-URLs echter Datenquellen (Stanford, PDS, …).
• Herkunft und Literatur der Operatoren — die Quellen der Forschung/Verfahren, auf denen diese Operatorfamilie beruht.
• Der kanonische Algorithmus (Autor, Jahr) und seine Anwendungen stehen im Familienleitfaden oben.
• photon_timeresolved — py -3.11 examples/photon_timeresolved.py
image2d als Eingabe)photon_sample · photon_statistics · photon_uncertainty · anscombe_inverse
transform)*Provenance: photoncount.py — PHOTON Operator-Registry. Diese Notiz wird von tools/opdocs.py md erzeugt (nicht von Hand bearbeiten).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.