本文最后更新于:2023年8月2日 下午
图像可以转换到其他空间进行分析和处理,本文记录 OpenCV 分析算子中的频域变换相关内容。
离散傅里叶变换
定义
- 对于任意以离散参数为索引的数值集合,都可以通过与连续傅里叶变换相似的方法来定义离散傅里叶变换(DFT)。对于$N$个复数$ {x_{0}, x_{1}, x_{2}, /ldots, x_{N-1}} $,一维 DFT 由如下公式(其中$ i=/sqrt{-1} $):
$$
g_{k}=\sum_{n=0}^{N-1} f_{n} e^{-\frac{2 \pi i}{N} k n}
$$
- 相似的,对于二维数值数组,也可以定义变换:
$$
g_{k_{x}, k_{y}}=\sum_{n_{x}=0}^{N_{x}-1} \sum_{n_{y}=0}^{N_{y}-1} f_{n_{x}, n_{y}} e^{-\frac{2 \pi i}{N}\left(k_{x} n_{x}+k_{y} n_{y}\right)}
$$
- 一般计算项数为$N$的的变换预计需要$O(N^2)$次运算。实际上,有几种快速傅里叶变换(FFT)算法可以在的复杂度内计算这些值。
cv2.dft()
计算矩阵的离散傅里叶变换
-
函数使用
cv2.dft()
函数实现离散傅里叶变换以及其逆变换(取决于flags
参数)。源矩阵src
必须是一维或二维的。结果矩阵dst
将具有与src
相同的类型和尺寸。参数
flags
是一个位域值,可以设置为cv2.DFT_INVERSE
,cv2.DFT_ROWS
,cv2.DFT_SCALE
,cv2.DFT_COMPLEX_OUTPUT
或cv2.DFT_REALOUTPUT
中的一个或多个。
1 |
|
-
flags 说明
-
如果设置为
cv2.DFT_INVERSE
,则完成逆变换。 -
如果设置标志为
cv2.DFT_ROWS
,则二维n×m输入被视为长度为m的n个不同的一维向量,并且每个这样的向量将独立变换。 -
标志
cv2.DFT_SCALE
通过将结果除以矩阵中的元素数来标准化结果,这通常用于DFT_INVERSE,因为它保证逆的逆将具有正确的标准化。 -
标志
cv2.DFT_COMPLEX_OUTPUT
:和cv2.DFT_REAL_OUTPUT
是有用的,因为当计算实数矩阵的傅里叶变换时,结果将有复共轭对称性。因此,即使结果是复数,结果矩阵的元素数量等于输入矩阵中的元素数量,而不是该数量的两倍。这样的压缩是cv2.dft()
的默认行为。 -
若要强制输出复数的形式,则需设置标志
cv2.DFT_COMPLEX_OUTPUT
。在逆变换的情况下,输入(通常)为复数,输出也为复数。然而,如果输入矩阵(对逆变换的情况)具有复共轭对称性(例如,如果它本身是实数矩阵的傅里叶变换的结果),那么逆变换将是一个实数矩阵。如果知道是这种情况,并且希望结果矩阵表示为一个实数矩阵(从而使用一半的内存量),则可以设置cv2.DFT_REAL_OUTPUT
标志。 -
请注意,如果设置
cv2.DFT_REAL_OUTPUT
标志,cv2.dft()
不会检查输入矩阵是否具有必要的对称性,它只是假定具有对称性。
-
-
nonzeroRows
cv2.dft()
的最后一个参数是nonzeroRows
,它默认为0,但如果设置它为任何非0值,将导致cv2.dft()
认为只有输入矩阵的前nonzeroRows
行是有意义的。如果cv2.DFT_INVERSE
被设置,那么就认为只有输出矩阵的前nonzeroRows
行是非零的。在使用cv2.dft()
计算卷积的互相关时,这个标志特别方便。 -
最佳尺寸
cv2.dft()
的性能很大程度上取决于传递给它的矩阵的确切尺寸,这种关系(性能与尺寸的关系)并不是线性的。只有一些尺寸是比其他尺寸表现出的性能更好。建议在将矩阵传递给cv2.dft()
时,首先在比当前矩阵大的尺寸中确定最佳尺寸,然后将矩阵扩展为该尺寸。OpenCV提供了一个合适的例程来计算这个值,称为cv2.getOptimalDFTSize()
。 -
示例代码
1 |
|
cv2.idft()
计算矩阵的离散傅里叶逆变换,
cv2.idft()
只是离散傅里叶逆变换的一个方便的简写。对cv2.idft()
的调用实际上相当
于调用带参数的cv2.dft(src, flags=cv2.DCT_INVERSE)
1 |
|
cv2.mulSpectrums()
方法实现频谱复数元素逐元素乘积
- 函数使用
1 |
|
其中 $a, b$ 为变量,同时为单通道频谱或双通道复数频谱
- 示例代码
1 |
|
表示复数 $(1+i, 1-i)$ 与 $(2+i, 1-2i)$ 逐元素乘积。
离散余弦变换
定义
$$ c_{k}=\left(\frac{1}{N}\right)^{\frac{1}{2}} x_{0}+\sum_{n=1}^{N-1}\left(\frac{2}{N}\right)^{\frac{1}{2}} x_{n} \cos \left(\left(k+\frac{1}{2}\right) \frac{n}{N} \pi\right) $$- 用于实信号的频域分析
- DCT 变换的由来
cv2.dct()
计算矩阵的离散余弦变换
-
函数使用
该函数根据
flags
参数的值执行离散余弦变换或离散余弦逆变换。源矩阵src
必须是一维或二维的,并且尺寸应该是偶数(如果需要,可以填充矩阵)。结果矩阵dst
将具有与src
相同的类型和尺寸。参数flags
是一个位域值,可以设置为cv2.DCT_INVERSE
或cv2.DCT_ROWS
中的一个或两个。
1 |
|
-
参数说明
src
需要为一维或二维的 float32 或 float64 数据flags
不设置默认正向变换flags
如果设置为cv2.DCT_INVERSE
,则实现逆变换而不是前向变换。flags
如果设置标志为cv2.DCT_ROWS
,则将二维n×m的输入视为长度为m的n个不同的一维向量。在这种情况下,每个这样的向量将被独立地变换。
-
最佳尺寸
cv2.dct()
的性能很大程度上取决于传递给它的矩阵的确切尺寸,这种关系(性能与尺寸的关系)并不是单调的。只有一些尺寸是比其他尺寸表现出的性能更好。建议在将矩阵传递给cv2.dct()
时,首先在比当前矩阵大的尺寸中确定最佳尺寸,然后将矩阵扩展为该尺寸。OpenCV 为你提供了一个合适的例程来计算这个值,称为cv2.getOptimalDFTSize()
。 -
示例代码
1 |
|
cv2.idft()
计算矩阵的离散傅里叶逆变换,
cv2.idft()
只是离散傅里叶逆变换的一个方便的简写。对cv2.idft()
的调用实际上相当
于调用带参数的cv2.dft(src, flags=cv2.DCT_INVERSE)
1 |
|
参考资料
- 《学习 OpenCV3》 第十二章
文章链接:
https://www.zywvvd.com/notes/study/image-processing/opencv/opencv-img-analysis/opencv-img-analysis/
“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信支付

支付宝支付