#include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include <iostream> #include <fstream> using namespace std; using namespace cv; int radius = 1;//截断频率 Mat img; /*(理想低通滤波器,巴特沃斯低通滤波器,高斯低通滤波器)*/ enum LPFILTER_TYPE { ILP_FILTER = 0, BLP_FILTER = 1, GLP_FILTER = 2 }; void fft2Image(InputArray _src, OutputArray _dst); Mat createLPFilter(Size size, float radius, int type, int n); void callback_lpFilter(Mat src, int lpType, Mat&result); int main() { Mat img = imread("1.jpg", 0); //数据类型转换,转换为 浮点型 Mat src_32; img.convertTo(src_32, CV_32FC1, 1.0, 0.0); /* -- 第二步:每一个数乘以(-1)^(r+c) -- */ for (int r = 0; r < src_32.rows; r++) { for (int c = 0; c < src_32.cols; c++) { if ((r + c) % 2) src_32.at<float>(r, c) *= -1; } } /* -- 第三、四步:补零和快速傅里叶变换 -- */ Mat src_dft; fft2Image(src_32, src_dft); //傅里叶谱 int lpType = 0; Mat lowpass; callback_lpFilter(src_dft,lpType, lowpass); imshow("d", lowpass); } void fft2Image(InputArray _src, OutputArray _dst) { //得到Mat类型 Mat src = _src.getMat(); //判断位深 CV_Assert(src.type() == CV_32FC1 || src.type() == CV_64FC1); CV_Assert(src.channels() == 1 || src.channels() == 2); int rows = src.rows; int cols = src.cols; //为了进行快速的傅里叶变换,我们经行和列的扩充,找到最合适扩充值 Mat padded; int rPadded = getOptimalDFTSize(rows); int cPadded = getOptimalDFTSize(cols); //进行边缘扩充,扩充值为零 copyMakeBorder(src, padded, 0, rPadded - rows, 0, cPadded - cols, BORDER_CONSTANT, Scalar::all(0)); //快速的傅里叶变换(双通道:用于存储实部 和 虚部) dft(padded, _dst, DFT_COMPLEX_OUTPUT); } //构造低通滤波器 Mat createLPFilter(Size size, float radius, int type, int n = 2) { Mat lpFilter = Mat::zeros(size, CV_32FC1); int rows = size.height; int cols = size.width; if (radius <= 0) return lpFilter; //构造理想低通滤波器 if (type == ILP_FILTER) { for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { float norm2 = pow(abs(float(r - rows/2)), 2) + pow(abs(float(c - cols/2)), 2); if (sqrt(norm2) < radius) lpFilter.at<float>(r, c) = 1; else lpFilter.at<float>(r, c) = 0; } } } //构造巴特沃斯低通滤波器 if (type == BLP_FILTER) { for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { lpFilter.at<float>(r, c) = float(1.0 / (1.0 + pow(sqrt(pow(r - rows / 2, 2.0) + pow(c -cols/2, 2.0)) / radius, 2.0*n))); } } } //构造高斯低通滤波 if (type == GLP_FILTER) { for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { lpFilter.at<float>(r, c) = float(exp(-(pow(c - cols / 2, 2.0) + pow(r - rows/2, 2.0)) / (2 * pow(radius, 2.0)))); } } } return lpFilter; } //低通滤波src傅里叶变换图像 void callback_lpFilter(Mat src,int lpType, Mat &result) { /* -- 第五步:构造低通滤波器 -- */ Mat lpFilter = createLPFilter(src.size(), radius, lpType, 2); /*-- 第六步:低通滤波器和图像快速傅里叶变换点乘 --*/ Mat F_lpFilter; F_lpFilter.create(src.size(), src.type()); for (int r = 0; r < F_lpFilter.rows; r++) { for (int c = 0; c < F_lpFilter.cols; c++) { //分别取出当前位置的快速傅里叶变换和理想低通滤波器的值 Vec2f F_rc = src.at<Vec2f>(r, c); float lpFilter_rc = lpFilter.at<float>(r, c); //低通滤波器和图像的快速傅里叶变换对应位置相乘 F_lpFilter.at<Vec2f>(r, c) = F_rc * lpFilter_rc; } } /* -- 第七、八步:对低通傅里叶变换执行傅里叶逆变换,并只取实部 -- */ dft(F_lpFilter, result, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT); /* -- 第九步:同乘以(-1)^(x+y) -- */ for (int r = 0; r < result.rows; r++) { for (int c = 0; c < result.cols; c++) { if ((r + c) % 2) result.at<float>(r, c) *= -1; } } //注意将结果转换 CV_8U 类型 result.convertTo(result, CV_8UC1, 1.0, 0); /* -- 第十步:截取左上部分,大小等于输入图像的大小 --*/ }