【OpenCV】实现图像FFT变换并进行滤波

实现图像FFT变换并进行滤波
环境:vs2017 + OpenCV 3.4.1
实验步骤:
(1)将输入图像转换成256×256大小,这样可以进行8次蝶形运算
【OpenCV】实现图像FFT变换并进行滤波
(2)将图像转换为灰度图像,并显示
【OpenCV】实现图像FFT变换并进行滤波
(3)设计FFT输入矩阵,该矩阵为2维双通道矩阵,第一个通道为实部,第二个通道为虚部,并将输入矩阵的值赋给实部
【OpenCV】实现图像FFT变换并进行滤波

(4)将输入矩阵按行进行一维FFT,256个点需进行8次蝶形运算,循环256次得到FFT中间过程矩阵

【OpenCV】实现图像FFT变换并进行滤波
(5)矩阵转置,进行列FFT,再次转置,得到FFT频谱矩阵,若要将频谱显示出来,需要求出频谱振幅矩阵,并转换为单通道整型矩阵
【OpenCV】实现图像FFT变换并进行滤波
【OpenCV】实现图像FFT变换并进行滤波
(6)带通滤波,滤波范围为60-100
【OpenCV】实现图像FFT变换并进行滤波
(7)将滤波后的矩阵进行IFFT,同样先对行进行FFT,转置后对列进行FFT
【OpenCV】实现图像FFT变换并进行滤波
(8)求幅值,并转换为单通道整型,并显示
【OpenCV】实现图像FFT变换并进行滤波
实验结果:
【OpenCV】实现图像FFT变换并进行滤波
FFT频谱
【OpenCV】实现图像FFT变换并进行滤波
滤波后FFT频谱

【OpenCV】实现图像FFT变换并进行滤波

核心代码:


void CPPSWDlg::fft1(Mat a,int mode) {//mode=1为FFT,mode=-1为IFFT
	int cols = a.cols;
	int length = a.cols;
	int rows = a.rows;
	printf("length=%d\n", cols);
	printf("rows=%d\n", rows);
	int ex = 0;
	int isLing = length;
	while (isLing != 0) {
		isLing = isLing / 2;
		ex += 1;
	}
	ex = ex - 1;
	printf("ex=%d\n", ex);
	int bit, kk;
	double xx;
	xx = -PI * 2.0 / (double)length;
	if (mode == 1) {
		xx = xx;
	}
	if (mode == -1) {
		xx = -xx;
	}

	int i, ii, j, k, l, w, j1, j2;
	int numb, lenb, timb;
	float xr, xi, yr, yi, nrml;
	for (l = 0; l < rows; l++) {//矩阵行数
		numb = 1;
		lenb = length;

		for (i = 0; i < ex; i++) {//蝶形运算次数
			lenb /= 2;
			timb = 0;
			for (j = 0; j < numb; j++) {//多少点的FFT
				w = 0;
				for (k = 0; k < lenb; k++) {//两点FFT
					j1 = timb + k;
					j2 = j1 + lenb;
					xr = a.at<Vec2f>(l, j1)[0];
					xi = a.at<Vec2f>(l, j1)[1];
					yr = a.at<Vec2f>(l, j2)[0];
					yi = a.at<Vec2f>(l, j2)[1];
					a.at<Vec2f>(l, j1)[0] = xr + yr;
					a.at<Vec2f>(l, j1)[1] = xi + yi;
					//printf("cplMat_src.at<Vec2f>(%d, %d)[0]=%f\n", l,j1,cplMat_src.at<Vec2f>(l, j1)[0]);
					//printf("cplMat_src.at<Vec2f>(%d, %d)[1]=%f\n",l,j1, cplMat_src.at<Vec2f>(l, j1)[1]);
					xr = xr - yr;
					xi = xi - yi;
					a.at<Vec2f>(l, j2)[0] = xr * cos(w*xx) - xi * sin(w*xx);
					a.at<Vec2f>(l, j2)[1] = xr * sin(w*xx) + xi * cos(w*xx);
					//printf("cplMat_src.at<Vec2f>(%d, %d)[0]=%f\n", l,j2,cplMat_src.at<Vec2f>(l, j2)[0]);
					//printf("cplMat_src.at<Vec2f>(%d, %d)[1]=%f\n",l,j2, cplMat_src.at<Vec2f>(l, j2)[1]);
					w += numb;
				}
				timb += (2 * lenb);
			}
			numb *= 2;
		}
		for (i = 0; i < length; i++) {
			for (kk = 0, ii = i, bit = 0; ; bit <<= 1, ii >>= 1) {
				bit = (ii & 1) | bit;
				if (++kk == ex) break;
			}
			cplMat_out.at<Vec2f>(l, i)[0] = a.at<Vec2f>(l, bit)[0];
			cplMat_out.at<Vec2f>(l, i)[1] = a.at<Vec2f>(l, bit)[1];
		}
		for (i = 0; i < length; i++) {
			a.at<Vec2f>(l, i)[0] = cplMat_out.at<Vec2f>(l, i)[0];
			a.at<Vec2f>(l, i)[1] = cplMat_out.at<Vec2f>(l, i)[1];
		}
		nrml = 1.0 / sqrt((double)length);
		//printf("nrml=%f\n", nrml);
		for (i = 0; i < length; i++) {
			a.at<Vec2f>(l, i)[0] *= nrml;
			a.at<Vec2f>(l, i)[1] *= nrml;
			//printf("cplMat_src.at<Vec2f>(%d, %d)[0]=%f\n", l, i, a.at<Vec2f>(l, i)[0]);
			//printf("cplMat_src.at<Vec2f>(%d, %d)[1]=%f\n", l, i, a.at<Vec2f>(l, i)[1]);
		}
	}
}