为了便于表示频谱信息和后续的傅里叶变换,我们需要从原本的基于像素位置的坐标空间,通过平移、拉伸,构建出原点在中心的、以基频为单位的波数坐标。
平移:居中处理
float nx = (float)id.x - (float)Size / 2.0;
float ny = (float)id.y - (float)Size / 2.0;转换前:id.x 和 id.y 是 GPU 线程的索引,范围通常是 $[0, Size-1]$
转换后:将坐标系的原点从左下角移动到网格的中心
在频率分析中,低频通常位于中心,平移操作后符合离散傅里叶变换(DFT)中对于对称频谱的处理习惯。
拉伸:单位转换
从 像素 到 波数
求目标函数:
$$ \vec{k} = f(\vec{n}) \quad,其中 \begin{cases} f(\vec{n}) \ne 0 \\ f(\vec{n}) \text{ 单调递增} \end{cases} $$在物理学中,波数 $k$ 与波长 $\lambda$ 的关系是
$$ k = \frac{2\pi}{\lambda} $$当波长 $\lambda$ 为 实际海面物理尺寸 $L$ ,即该波恰好覆盖正片海域时,
$$ k=\frac{2\pi}{L} $$设该波为要模拟的最大波长,则目标函数在零点时等于该值,
$$ k=f(0)=\frac{2\pi}{L} $$由瞪眼法得,
$$ \vec{k} = f(\vec{n})=(\vec{n} \pm 1)\frac{2\pi}{L} $$代码表示为,
float kx = (nx + sign(nx)) * (2.0 * PI / Length);
float ky = (ny + sign(ny)) * (2.0 * PI / Length);注意
这个拉伸公式并不是唯一的,只要变换后的意义正确,可以随意定义,如:
- 增大坐标 $\vec{n}$ 偏移远离零点,避免巨大的长波
- 添加缩放因子,增加坐标系精度、剔除小波
变换后的意义

在经过变换后,
- 越靠近中心的坐标点,所表示的波波数越小(波长小、频率低)
- 越靠近边缘的坐标点,所表示的波波数越大(波长小、频率高)