phase_displacement — MOTIONMAG measure op

데이터 종류: videotable

호출: import motionmag; motionmag.phase_displacement(video, f_lo, f_hi, fps, scales: 'int' = 4, orientations: 'int' = 4) -> 'dict'(또는 opsmotionmag.get("phase_displacement"))

사용법

국소 위상으로부터의 서브픽셀 변위장 -> `dict`.

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

The quantitative sibling of :func:motion_magnify: nothing is amplified and

nothing is re-rendered, the displacement itself is returned in pixels.

For each oriented sub-band, the temporal phase deviation `dphi(t)` (taken

against the band's temporal mean as the wrapped angle in `(-pi, pi]` —

never unwrapped in time, for the reason given in the design note above

`_AMP_FLOOR` — then band-passed) obeys

`dphi = -(kx*dx + ky*dy), where (kx, ky)` is the band's local

spatial frequency in radians per pixel — computed exactly as

`Im(conj(z) grad z)/|z|^2` with a spectral derivative, not from the band's

nominal centre. Each band contributes one linear constraint on the same

two unknowns, so the bands are combined per pixel by weighted least squares

with weights `|z|^2` (a band with no contrast gets no vote).

Returns ``{"dx": (T, H, W), "dy": (T, H, W), "weight": (H, W),

"valid": (H, W) bool, "rank": (H, W) int8, "fps": ..., "band_hz": ...,

"wrap_limit_px": ..., "reference_coherence": ...}`. dx/dy` follow

:mod:flow: `dx is column motion, dy` row motion, positive towards

increasing index, and both are zero-mean along time because the band-pass

removed DC.

`rank` says how much of the 2-D displacement the data could constrain at

each pixel: 2 = both components, 1 = the aperture problem (every band

with contrast there shares one orientation, so only the component along it

is observable — that component is returned and the unobservable direction is

exactly 0), 0 = no contrast at all, both zero. Measured on a purely

horizontal grating moving 0.3 px horizontally, every pixel is rank 1 and the

answer is `dx = 0.3000000000000001, dy = 0.0` exactly.

Accuracy and where it stops (measured, 64x64x64 clip at 32 fps, 8 px

horizontal grating, 4 Hz bin-centred, noiseless, defaults; the error is on

the peak of the recovered waveform):

============== ============== ============== ===================

true d (px) k*d (rad) measured (px) relative error

============== ============== ============== ===================

0.001 0.0008 0.00100000 8.7e-15

0.010 0.0079 0.01000000 3.1e-15

0.100 0.0785 0.10000000 1.8e-15

0.500 0.3927 0.50000000 6.7e-16

1.000 0.7854 1.00000000 4.4e-16

2.000 1.5708 2.00000000 6.7e-16

3.000 2.3562 3.00000000 5.9e-16

3.050 2.3954 3.05000000 2.9e-16

3.100 2.4347 1.72842712 4.4e-01 <- broken

4.000 3.1416 2.10461396 4.7e-01 <- broken

6.000 4.7124 2.35441757 6.1e-01 <- broken

============== ============== ============== ===================

Exact to rounding — and then it stops, abruptly, between 3.05 and 3.10 px.

That boundary is closed-form, and it is *not* the naive phase-wrap bound.

The temporal phase reference is the band's temporal mean `z_mean`, and for

a sinusoidal displacement of amplitude `A` that mean equals

`c * J0(k*A) — a Bessel function. At k*A = 2.4048`, the first zero of

`J0`, the reference amplitude passes through zero and its phase flips by

`pi; every deviation measured against it is then wrong by pi`. For the

8 px grating that is `A = 2.4048/(2*pi/8) = 3.0619` px, which is exactly

where the table breaks. `reference_coherence` in the return is

`|z_mean| / mean_t|z|, i.e. |J0(k*A)|` blended over the bands, and it

falls monotonically from 1.00000 at 0.001 px to 0.50252 at the 3.05 px edge

— a runtime warning that the reference is going degenerate.

Beyond that sits the harder bound `|k*d| < pi` (half a band wavelength,

reported as `wrap_limit_px` from the measured local frequencies), which no

phase-based method can pass with a single band.

Under noise the accuracy is set by the noise, not by the method: on the same

clip with `A = 0.5` px, additive sigma = 0.001 / 0.01 / 0.05 gives

relative errors 2.2e-04 / 1.8e-03 / 1.9e-03.

자세한 사용 가이드

motion_magnification 패밀리 가이드

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

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

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

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

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

motion_magnificationpy -3.11 examples/motion_magnification.py

quaternion_monogenicpy -3.11 examples/quaternion_monogenic.py

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

complex_steerable_reconstruct

같은 카테고리(measure)

displacement_series


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

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