实现图像FFT变换并进行滤波
环境:vs2017 + OpenCV 3.4.1
实验步骤:
(1)将输入图像转换成256×256大小,这样可以进行8次蝶形运算
(2)将图像转换为灰度图像,并显示
(3)设计FFT输入矩阵,该矩阵为2维双通道矩阵,第一个通道为实部,第二个通道为虚部,并将输入矩阵的值赋给实部
(4)将输入矩阵按行进行一维FFT,256个点需进行8次蝶形运算,循环256次得到FFT中间过程矩阵
(5)矩阵转置,进行列FFT,再次转置,得到FFT频谱矩阵,若要将频谱显示出来,需要求出频谱振幅矩阵,并转换为单通道整型矩阵
(6)带通滤波,滤波范围为60-100
(7)将滤波后的矩阵进行IFFT,同样先对行进行FFT,转置后对列进行FFT
(8)求幅值,并转换为单通道整型,并显示
实验结果:
FFT频谱
滤波后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(l, j1)[0];
xi = a.at(l, j1)[1];
yr = a.at(l, j2)[0];
yi = a.at(l, j2)[1];
a.at(l, j1)[0] = xr + yr;
a.at(l, j1)[1] = xi + yi;
//printf("cplMat_src.at(%d, %d)[0]=%f\n", l,j1,cplMat_src.at(l, j1)[0]);
//printf("cplMat_src.at(%d, %d)[1]=%f\n",l,j1, cplMat_src.at(l, j1)[1]);
xr = xr - yr;
xi = xi - yi;
a.at(l, j2)[0] = xr * cos(w*xx) - xi * sin(w*xx);
a.at(l, j2)[1] = xr * sin(w*xx) + xi * cos(w*xx);
//printf("cplMat_src.at(%d, %d)[0]=%f\n", l,j2,cplMat_src.at(l, j2)[0]);
//printf("cplMat_src.at(%d, %d)[1]=%f\n",l,j2, cplMat_src.at(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(l, i)[0] = a.at(l, bit)[0];
cplMat_out.at(l, i)[1] = a.at(l, bit)[1];
}
for (i = 0; i < length; i++) {
a.at(l, i)[0] = cplMat_out.at(l, i)[0];
a.at(l, i)[1] = cplMat_out.at(l, i)[1];
}
nrml = 1.0 / sqrt((double)length);
//printf("nrml=%f\n", nrml);
for (i = 0; i < length; i++) {
a.at(l, i)[0] *= nrml;
a.at(l, i)[1] *= nrml;
//printf("cplMat_src.at(%d, %d)[0]=%f\n", l, i, a.at(l, i)[0]);
//printf("cplMat_src.at(%d, %d)[1]=%f\n", l, i, a.at(l, i)[1]);
}
}
}