利用DFT可以大大加快卷积运算的速度,因为卷积定理说明空间域的卷积运算可以转换为频域的乘法运算。
-------------------------------------------------------------------------------
GetOptimalDFTSize |
GetOptimalDFTSize |
GetSubRect |
GetSubRect |
DFT |
DFT |
-------------------------------------------------------------------------------
/*code*/
#include <highgui.h>
#include <cv.h>
int main(int argc, char** argv)
{
int M1 = 2, M2 = 2, N1 = 2, N2 = 2;
CvMat* A = cvCreateMat( M1, N1, CV_32F ); //创建2行2列的32位浮点矩阵
CvMat* B = cvCreateMat( M2, N2, A->type );
//创建矩阵存放卷积结果have only abs(M2-M1)+1×abs(N2-N1)+1 part of the full convolution result
CvMat* convolution = cvCreateMat( A -> rows + B -> rows - 1,
A -> cols + B -> cols - 1, A -> type );
int dft_M = cvGetOptimalDFTSize( A -> rows + B -> rows - 1 ); //对于给定的矢量尺寸返回最优DFT尺寸
int dft_N = cvGetOptimalDFTSize( A -> cols + B -> cols - 1 );
CvMat* dft_A = cvCreateMat( dft_M, dft_N, A -> type );
CvMat* dft_B = cvCreateMat( dft_M, dft_N, B -> type );
CvMat tmp;
// copy A to dft_A and pad dft_A with zeros
cvGetSubRect( dft_A, &tmp, cvRect( 0, 0, A -> cols, A -> rows ) ); //返回输入的图像或矩阵的矩形数组子集的矩阵头
cvCopy( A, &tmp );
cvGetSubRect( dft_A, &tmp, cvRect( A -> cols, 0, dft_A -> cols - A -> cols, A -> rows ) );
cvZero( &tmp );
// no need to pad bottom part of dft_A with zeros because of
// use nonzero_rows parameter in cvDFT() call below
cvDFT( dft_A, dft_A, CV_DXT_FORWARD, A -> rows ); //执行一维或者二维浮点数组的离散傅立叶正变换或者离散傅立叶逆变换
// repeat the same with the second array B
//
cvGetSubRect( dft_B, &tmp, cvRect( 0, 0, B -> cols, B -> rows ) ); //返回输入的图像或矩阵的矩形数组子集的矩阵头
cvCopy( B, &tmp );
cvGetSubRect( dft_B, &tmp, cvRect( B -> cols, 0, dft_B -> cols - B -> cols, B -> rows ) );
cvZero( &tmp );
cvDFT( dft_B, dft_B, CV_DXT_FORWARD, B -> rows );
cvMulSpectrums( dft_A, dft_B, dft_A, 0 ); //两个傅立叶频谱的每个元素的乘法
cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, convolution -> rows );
cvGetSubRect( dft_A, &tmp, cvRect( 0, 0, convolution -> cols, convolution -> rows ) );
cvCopy( &tmp, convolution );
cvReleaseMat( &dft_A );
cvReleaseMat( &dft_B );
return 0;
}