离散傅里叶变换(DFT)对一张图像使用傅里叶变换就是将它分解为正弦和余弦两部分,也就是将图像从空间域转换到频域。
这一转换的理论基础为:任一函数都可以表示成无数个正弦和余弦函数的和的形式,傅里叶变换就是一个用来将函数分解的工具。
转换之后的频域值是复数,因此显示傅里叶变换之后的结果需要使用实数图形加虚数图像,或者幅度图像加相位图像的形式。
幅度图像实际上包含了我们需要的几乎所有信息,但如果要进行逆傅里叶变换,显然两类方法各自都必须保留两种图像。
在频域中,高频部分代表了图像的细节、纹理信息;低频部分代表了图像的轮廓信息。如果对一幅精细的图像使用低通滤波器,那么滤波后就只有轮廓了。同时,如果能确定噪声的范围,就可以消除它。
dft()函数
dft函数的作用是对一维或二维浮点数数组进行正向或反向离散傅里叶变换。
void dft(InputArray src, OutputArray dst, int flags=0,int nonzeroRows=0);
第一个参数,InputArray类型的src,输入矩阵,可以为实数或者虚数;
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里。其尺寸和类型取决于标识符flags;
第三个参数,int类型的flags。有默认值0。
DFT_INVERSE:用一维或二维逆变换代替默认的正向变换;
DFT_SCALE:缩放比例标识符,输出的结果都会以1/N进行缩放,通常结合INVERSE使用;
DFT_ROWS:对输入矩阵的每行进行正向或反向的变换,此标识符可以在处理多种矢量的时候用于减小资源开销,这些处理常常是三维或高维变换等复杂操作。
DFT_CONPLEX_OUTPUT:进行一维或二维实数数组正变换。这样的结果虽然是复数阵列,但拥有复数的共轭对称性,所以可以被写成一个拥有同样尺寸的实数阵列。
DFT_REAL_OUTPUT:进行一维或二维数组反变换,结果通常是一个大小相同的复数矩阵。如果输入的矩阵有复数的共轭对称性,便会输出实矩阵。
第四个参数int类型的nonzeroRows,有默认值0。
void convolveDFT(InputArray A, InputArray B, OutputArray C)
{
//初始化输出矩阵
C.create(abs(A.rows - B.rows + 1), abs(A.cols - B.cols) + 1, A.type());
Size dftSize;
//计算DFT变换的尺寸
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);
//分配临时缓冲区并初始化置零
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));
//分别复制A和B到tempA和tempB的左上角
Mat roiA(tempA, Rect(0, 0, A.cols, A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0, 0, B.cols, B.rows));
B.copyTo(roiB);
//就地操作,进行快速傅里叶变换,并将nonzeroRows参数置为非0,以更快的加以处理。
dft(tempA, tempA, 0, A.rows);
dft(tempB, tempB, 0, B.rows);
//将得到的频谱相乘,结果存放于tempA中
mulSpectrums(tempA, tempB, tempA);
//将结果变换为频域
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows);
//将结果复制到C中
tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);
}
MulSpectrums的作用是计算两个傅里叶频谱的每个元素的乘法,前两个参数为输入的参加乘法运算的两个矩阵,第三个参数为得到的乘法结果矩阵。