概述
逆FFT 实现了二维图像的逆傅里叶变换,支持实值和复值输出。给定一个二维频谱(频域),它返回空间域上的图像表示。它是 FFT 算法的精确逆运算。
以幅度谱作为输入 | 在空间域中输出 |
| |
实现
逆快速傅里叶变换与正向 FFT 的 实现 非常相似,除了指数的符号,这里是正号。
\[ I[m,n] = \frac{1}{MN} \sum^{M-1}_{u=0} \sum^{N-1}_{v=0} I'[u,v] e^{+2\pi i (\frac{um}{M}+\frac{vn}{N})} \]
其中
- \(I'\) 是频域中的输入图像
- \(I\) 是其空间域表示
- \(M\times N\) 是输入的维度
默认情况下,应用归一化因子 \(\frac{1}{MN}\) 以使 IFFT 成为 FFT 的精确逆运算。由于这会带来性能损失,并且可能不需要归一化,用户可以传递标志 VPI_DENORMALIZED_OUTPUT 给 vpiSubmitIFFT,以指示输出必须保持非归一化状态。
与直接 FFT 一样,根据 \(N\) 的值,采用不同的技术以获得最佳性能
- CPU 后端
- 当 \(N\) 可以分解为 \(2^a \times 3^b \times 5^c\) 时的快速路径
- CUDA 后端
- 当 \(N\) 可以分解为 \(2^a \times 3^b \times 5^c \times 7^d\) 时的快速路径
一般来说,素因子越小,性能越好,即,2 的幂次是最快的。
IFFT 支持以下变换类型
数据布局
数据布局严格取决于变换类型。在一般的 C2C 变换情况下,输入和输出数据都应为 VPI_IMAGE_FORMAT_2F32 类型且具有相同的大小。在 C2R 模式下,类型为 VPI_IMAGE_FORMAT_2F32 的每个输入图像行 \((X_1,X_2,\dots,X_{\lfloor\frac{N}{2}\rfloor+1})\) (仅包含非冗余值) 会生成类型为 VPI_IMAGE_FORMAT_F32 的行 \((x_1,x_2,\dots,x_N)\),表示整个图像。在这两种情况下,输入和输出图像的高度相同。
- 注意
- 在首次调用 vpiSubmitIFFT 时以及每次输入或输出行步幅相对于上次调用发生更改时,都可能发生内存分配。
C API 函数
有关实现该算法的限制、约束和后端的列表,请查阅以下函数的参考文档
- 注意
- 此算法要求系统中安装库 libcufft.so.10。
用法
语言
- 导入 VPI 模块
- 在 VPI 图像输入上运行 C2R IFFT,频谱数据格式为
vpi.Format._2F32
。生成的 VPI 图像格式为 vpi.Format.F32
。操作由 CUDA 后端执行。with vpi.Backend.CUDA
output = input.irfft()
- 初始化阶段
- 包含定义逆 FFT 函数的头文件。
- 定义输入频谱图像。由于我们执行的是 C2R IFFT,因此输入宽度必须为 \(\lfloor \frac{w}{2} \rfloor+1\),其中 \(w\) 是输出图像宽度。输入和输出高度必须匹配。图像格式必须为 VPI_IMAGE_FORMAT_2F32。
struct VPIImageImpl * VPIImage
图像的句柄。
- 创建输出图像。同样,由于是 C2R IFFT,输出类型必须为 VPI_IMAGE_FORMAT_F32。我们传递 0 作为标志,以使函数返回归一化输出。
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
使用指定的标志创建空的图像实例。
- 在 CUDA 后端上创建 IFFT 负载 (payload)。输入为复数,输出为实数。问题大小指的是输出大小。
VPIStatus vpiCreateIFFT(uint64_t backends, int32_t outputWidth, int32_t outputHeight, const VPIImageFormat inFormat, const VPIImageFormat outFormat, VPIPayload *payload)
为逆快速傅里叶变换算法创建负载 (payload)。
struct VPIPayloadImpl * VPIPayload
算法负载 (payload) 的句柄。
@ VPI_BACKEND_CUDA
CUDA 后端。
- 创建流 (stream),算法将提交到该流中执行。
struct VPIStreamImpl * VPIStream
流 (stream) 的句柄。
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
创建流 (stream) 实例。
- 处理阶段
- 将 IFFT 算法提交到流 (stream),传递输入频谱和输出缓冲区。它将在 CUDA 后端执行,因为负载 (payload) 是在那里创建的。
VPIStatus vpiSubmitIFFT(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIImage output, uint64_t flags)
在单个图像上运行逆快速傅里叶变换。
- 等待直到处理完成。
VPIStatus vpiStreamSync(VPIStream stream)
阻塞调用线程,直到此流队列中的所有提交命令都完成(队列为空)...
- 现在使用您喜欢的方法显示 output。
- 清理阶段
- 释放流 (stream)、负载 (payload) 以及输入和输出图像所持有的资源。
void vpiImageDestroy(VPIImage img)
销毁图像实例。
void vpiPayloadDestroy(VPIPayload payload)
释放负载 (payload) 对象和所有相关资源。
void vpiStreamDestroy(VPIStream stream)
销毁流 (stream) 实例并释放所有硬件资源。
有关更多信息,请参阅 VPI - 视觉编程接口 的 “C API 参考” 部分中的 快速傅里叶变换。
性能
有关如何使用下面的性能表的信息,请参阅 算法性能表。
在比较测量结果之前,请查阅 比较算法运行时间。
有关性能基准测试方式的更多信息,请参阅 性能基准。
-