tb_qft2 — 2D typed op

• 資料種類:qimage → qimage

• 呼叫:fullseye.apply(img, "tb_qft2", a=0.5, b=0.5)(2-D 的模型是一張圖 + 兩個純量旋鈕 a,b∈[0,1])

tb_qft2: input → output

*圖為在 128×128 合成輸入上實際執行的輸出。左為輸入,右為輸出。點雲以俯視散點顯示(亮度 = z),一維序列為折線,體資料為沿 z 的最大值投影,影片為中間影格,複數影像為振幅;無法成像的回傳值直接顯示數值。*

*旋鈕 a 不改變輸出(實測: 0.1 / 0.5 / 0.9 相同)。*

*旋鈕 b 不改變輸出(實測: 0.1 / 0.5 / 0.9 相同)。*

階段(前置運算子 → 本運算子,由左至右):

▸ tb_qft2: 處理階段 (文件網站)

換別的影像(合成場景 / 照片 / 硬幣。上排為輸入,下排為對應輸出。旋鈕取預設):

▸ tb_qft2: 其他輸入影像 (文件網站)

用法

四元數(超複數)二維傅立葉變換。→ (H, W, 4) 置中頻譜。

> 以下的詳細說明為原文 —— 摘要與標題已翻譯。

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

How it is computed, and why that is not a shortcut

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 _mu_basis).

Honest accounting against the channelwise baseline

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.

Typed bridge of the quat op qft2 into the 2-D evolution registry: the same implementation, called under the op(v, a, b) convention. This op has no tunable parameter; a and b are unused.

參考(範例資料、文獻)

• 範例資料目錄(下載 URL / 授權) —— 2-D 用 skimage.data(BSD/公有領域)加合成圖,3-D 給出真實資料源(Stanford/PDS 等)的下載 URL。

• 運算子來歷與參考文獻 —— 該運算子族所依據的研究/方法出處。

在 Studio 中試試

下面的程式已確認可以執行(與圖相同的輸入)。在 Studio 說明中,此區塊會變成按鈕,可當場載入並執行。

img_to_rgb 0.50 0.50
tb_rgb_to_quaternion 0.50 0.50
tb_qft2 0.50 0.50

▸ 載入此管線  ·  載入並執行

可執行的範例(實際呼叫該運算子並已驗證的樣例)

下面的範例呼叫的是底層帳本運算子 qft2。此橋接運算子只是把同一實作適配為 fn(v, a, b) 慣例,行為完全相同(只是呼叫形式不同)。

• quaternion_monogenic — py -3.11 examples/quaternion_monogenic.py

型別可銜接的下一個運算子(可接受 qimage 作為輸入)

identity · tb_quaternion_to_rgb · tb_quat_norm · tb_quat_conjugate_image · tb_quat_normalize_image · tb_monogenic_amplitude · tb_monogenic_phase · tb_monogenic_orientation

同類別(typed)

tb_points_to_voxel · tb_estimate_point_normals · tb_iss_keypoints · tb_project_points · tb_render_point_depth · tb_statistical_outlier_removal · tb_radius_outlier_removal · tb_voxel_grid_downsample


*Provenance: ops.py — 2D 運算子登記表。本條目由 tools/opdocs.py md 自動產生(請勿手動編輯)。*

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