fourier opqimage → qimageimport fullseye as fs; fs.ledger.qft2(qimage, side, mu=None) -> 'np.ndarray' (実装を直接呼ぶなら import quatimage; quatimage.qft2(qimage, side, mu=None) -> 'np.ndarray'、台帳から引くなら opsquat.get("qft2"))Quaternion (hypercomplex) 2-D Fourier transform. → (H, W, 4) centred spectrum.
The colour analogue of complexops.cx_fft: a colour image is transformed
as one hypercomplex signal rather than three unrelated real ones. The
kernel is exp(-mu * 2*pi*(u*x/W + v*y/H)) for a unit pure quaternion
mu (default: the grey axis of RGB, Sangwine’s choice), and because
quaternions do not commute the kernel can be applied on either side:
side="left" — F[u,v] = sum_{x,y} E(x,y,u,v) * f[x,y]side="right" — F[u,v] = sum_{x,y} f[x,y] * E(x,y,u,v)The argument is required. Left and right are not a sign convention. On
the fuzzer’s (32, 32) dichromatic render they differ by
max|F_L - F_R| = 19.11 against a peak modulus of 1045 (1.8 % of full
scale) and on a random colour field by 33.35 against 892.9 (3.7 %; another seed
gives 34.05 against 892) —
with no exception and no NaN to mark the difference. Mixing them across a
round trip is much worse, because there the disagreement is not attenuated
by the spectrum’s dynamic range: iqft2(qft2(q, "left"), "right") returns
an image whose error reaches 1.113 on data whose own range is 0.9994
— a completely different picture that still looks like a picture. (On the
grey-axis-dominated dichromatic render the same mistake costs only 0.054
against a range of 1.076, which is the dangerous case: a 5 % error is
exactly the size that survives a visual check.)
The spectrum is returned centred (DC at the array centre, via
fftshift), matching the convention complexops.cx_fft established for
the cimage sort. :func:iqft2 un-centres before inverting, and the round
trip is exact: measured max|iqft2(qft2(q, s), s) - q| = 2.22e-15 for both
sides on a standard-normal (32, 32, 4) field.
Every quaternion splits as q = A + B*nu with A, B in the commutative
subfield generated by mu (the symplectic decomposition, Ell &
Sangwine 2007). The kernel commutes with A and anti-commutes past
nu, so the whole transform reduces to two ordinary complex FFTs — for
the left transform both with the standard kernel, for the right one of them
with the conjugate kernel. That reduction is what makes left and right
differ, and it is verified against a brute-force O(N^2) quaternion DFT
written straight from the definition, on a 4x4 image, for three different
mu and both sides: the largest disagreement over all six combinations is
8.2e-15. The fast path is checked against the definition, not against
itself. The choice of the internal nu is likewise verified not to matter
(two different nu, max difference 1.4e-14 — see :func:_mu_basis).
Because the decomposition above is linear in the channels, the QFT is a
fixed recombination of the three per-channel complex FFTs: rebuilding
qft2(q, "left") from three numpy.fft.fft2 calls on the R, G and B
planes agrees to max|err| = 1.14e-13. So this transform buys no
information a channelwise FFT does not already contain, and this module
does not claim it does. It also does not buy speed — it moves four real
transforms’ worth of data where the channelwise route moves three, and pays
for the symplectic pack/unpack on top: measured on (256, 256), best of
20, 8.246 ms against 3.409 ms, i.e. 2.42x slower (run to run, 2.3x-2.4x). What it buys is that
the four numbers stay one algebraic object, so a rotor can be applied to the
spectrum and the colour meaning of mu survives the transform.
Raises ValueError: qimage is not a valid (H, W, 4) field;
side is not 'left' / 'right'; mu is not a finite non-zero
3-vector.
py -3.11 examples/quaternion_monogenic.pyqimage を入力に取れる)quaternion_to_rgb · quat_norm · quat_conjugate_image · quat_normalize_image · quat_image_multiply · monogenic_amplitude · monogenic_phase · monogenic_orientation
fourier)Provenance: quatimage.py — QUAT operator registry. この per-op ノートは tools/opdocs.py md が自動生成(手編集しない)。
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.