anscombe_transform — PHOTON transform op

데이터 종류: image2dimage2d

호출: import photoncount; photoncount.anscombe_transform(image, gain=1.0, read_sigma=0.0, offset=0.0, clip=False)(또는 opsphoton.get("anscombe_transform"))

사용법

Anscombe 분산 안정화 변환: 푸아송 계수 -> 분산 약 1.

> 아래 상세 설명은 원문입니다 —— 요약과 제목은 번역되어 있습니다.

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 -> :func:anscombe_inverse.

The generalised form (Starck/Murtagh/Bijaoui) also absorbs the sensor's

analogue chain, and takes exactly the parameters

:func: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

:func: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.

자세한 사용 가이드

photon_timeresolved 패밀리 가이드

참고(샘플 데이터·문헌)

• 샘플 데이터 카탈로그(DL URL / 라이선스) —— 2-D 는 skimage.data(BSD/public)+ 합성, 3-D 는 실데이터 소스(Stanford/PDS 등)의 DL URL.

• 연산자의 내력·참고문헌 —— 이 연산자 족의 바탕이 된 연구/기법의 출처.

• 알고리즘의 정전(저자·연도)과 용도는 위의 패밀리 사용 가이드에 적혀 있습니다.

실행 가능한 예제(이 연산자를 실제로 호출하는 검증된 샘플)

photon_timeresolvedpy -3.11 examples/photon_timeresolved.py

타입이 이어지는 다음 연산자(image2d 를 입력으로 받는 것)

photon_sample · photon_statistics · photon_uncertainty · anscombe_inverse

같은 카테고리(transform)

anscombe_inverse


*Provenance: photoncount.py — PHOTON 연산자 레지스트리. 이 op 노트는 tools/opdocs.py md 가 자동 생성합니다(직접 편집하지 마세요).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.