Opencv实现MATLAB fft2 函数

毕设是图像处理方面的,在根据文献实现二维傅里叶变换时,因c++输出结果一直与MATLAB输出的不同,所以屡屡碰壁。 结果今天突然搞对了,很开心。 其实网上有实现代码,但因为没有明显以输出例子对比的,所以其实很多时候我已经实现对了,但因为输出形式不对,或者把复数形式计算成幅值输出,一直在修改,特地写这篇总结前人的成果,防止新人因输出形式不对一直在瞎调。参考博客:https://blog..net/keith_bb/article/details/53389819 先以一个一维数组为例:

>> psf=[-1,0,1;0,0,0;0,0,0];
>> psf=single(psf)

psf =

  3×3 single 矩阵

    -1     0     1
     0     0     0
     0     0     0
>>psf=fft2(psf)

psf =

  3×3 single 矩阵

   0.0000 + 0.0000i  -1.5000 + 0.8660i  -1.5000 - 0.8660i
   0.0000 + 0.0000i  -1.5000 + 0.8660i  -1.5000 - 0.8660i
   0.0000 + 0.0000i  -1.5000 + 0.8660i  -1.5000 - 0.8660i

c++实现代码为:

Mat fft222(Mat &I)
{
          
   
	Mat padded;          //以0填充输入图像矩阵
	int m = getOptimalDFTSize(I.rows);
	int n = getOptimalDFTSize(I.cols);

	//填充输入图像I,输入矩阵为padded,上方和左方不做填充处理
	copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

	Mat planes[] = {
          
    Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };
	Mat complexI;
	merge(planes, 2, complexI);     //将planes融合合并成一个多通道数组complexI

	dft(complexI, complexI);        //进行傅里叶变换

									//计算幅值,转换到对数尺度(logarithmic scale)
									//=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
	split(complexI, planes);        //planes[0] = Re(DFT(I),planes[1] = Im(DFT(I))
									//即planes[0]为实部,planes[1]为虚部
	for (int i = 0;i < 3;i++)
	{
          
   
		for (int j = 0;j < 3;j++)
		{
          
   
			cout<<planes[0].at<float>(i, j)<<"+"<< planes[1].at<float>(i, j)<<"i"<<" ";
		}
		cout << endl;
	}
	return planes[0];
}


int main(int argc, const char ** argv)
{
          
   
	Mat psf=Mat::zeros(3, 3, CV_32FC1);
	psf.at<float>(0, 0) = -1;
	psf.at<float>(0, 2) = 1;
	psf = fft222(psf);
	waitKey();
	system("pause");
	return 0;
}

输出: 0+0i -1.5+0.866025i -1.5+ -0.866025i 0+0i -1.5+0.866025i -1.5+ -0.866025i 0+0i -1.5+0.866025i -1.5+ -0.866025i 请按任意键继续. . .

经验分享 程序员 微信小程序 职场和发展