赞
踩
第四步:利用傅里叶变换的快速算法得到复数矩阵F。
2、巴特沃斯低通滤波器
3、高斯低通滤波器
记glpFilter=[glpFilter(r,c)]H×W;
-
-
- // 快速傅里叶变换
- void fft2Image(InputArray image, OutputArray F)
- {
- //的到Mat 的类型
- Mat Image = image.getMat();
- int rows = Image.rows;
- int cols = Image.cols;
- // 获得最佳两列
- int r = getOptimalDFTSize(rows);
- int c = getOptimalDFTSize(cols);
-
- // 在左侧和下面进10
- Mat f;
- copyMakeBorder(Image, f, 0, r - rows, 0, c - cols, BORDER_CONSTANT,Scalar::all(0));
- // 两个通道,第一个通道用存储实部 第二个通道是存放虚部的
- dft(f, F, DFT_COMPLEX_OUTPUT);
-
- //傅里叶逆变换
- //dft(f, F, DFT_INVERSE+DFT_REAL_OUTPUT+DFT_SCALE);//只返回实部
- }
-
-
- // 幅度谱
- void amplitudeSpectrum(InputArray _srcfft, OutputArray _dstSpectrum)
- {
- if (_srcfft.channels() != 2) return ;
- // 如果是两个通道则开始分离通道
-
- vector<Mat> FFT2Channels;
- split(_srcfft, FFT2Channels);
-
- // 计算傅里叶变换幅度值 sqrt(pow(r,2)+pow(L,2))
- magnitude(FFT2Channels[0], FFT2Channels[1], _dstSpectrum);
-
- }
- // 傅里叶谱的灰度级显示
- Mat graySpectrum(Mat s)
- {
- Mat dst;
- log(s + 1, dst);
- // 归一化
- normalize(dst,dst,0,1,NORM_MINMAX);
- // 为了显示 灰度级
- dst.convertTo(dst,CV_8UC1,255,0);
- return dst;
- }
- // 计算傅里叶变换的相位角==phase 算子
- Mat phaseS(Mat sfft)
- {
- // 相位谱
- Mat phase;
- phase.create(sfft.size(), CV_64FC1);
- // 分离通道
- vector<Mat> fft2Channels;
- split(sfft,fft2Channels);
- // 开始计算相位谱
- for (int r = 0; r < phase.rows;r++) {
- for (int c = 0; c < phase.cols; c++) {
- // 实部 虚部
- double real = fft2Channels[0].at<double>(r,c);
- double img = fft2Channels[1].at<double>(r,c);
- // atan2 的返回值就是【0,180】,【-180,0】
-
- phase.at<double>(r, c) = atan2(img,real);
- }
- }
- return phase;
- }
- // -----------------------------------------------------------
-
- #if 1 //低通滤波
-
- enum typeFilter
- {
- ILPFILTER,
- BLPFILTER,
- GLPFILTER,
- };
- Mat createFilter(Size size, Point center,float radius, int type, int n = 2)
- {
-
- Mat ilpFilter = Mat::zeros(size,CV_32FC1); // 定义一个size大小的滤波器
- int rows = size.height;
- int cols = size.width;
-
- if (radius <= 0)return ilpFilter;
-
-
- // 构建理想的低通滤波器
- if (type== ILPFILTER)
- {
- for (int r=0;r< rows;r++)
- {
- for (int c = 0; c < cols;c++)
- {
- // 计算距离
- float norm2 = pow(abs(float(r - center.y)), 2)+ pow(abs(float(r - center.y)), 2);
- if (norm2 < radius)
- {
- ilpFilter.at<float>(r, c) = 1;
- }
- else
- {
- ilpFilter.at<float>(r, c) = 0;
- }
-
- }
- }
- }
- //
- else if(type == BLPFILTER)
- {
- for (int r = 0; r < rows; r++)
- {
- for (int c = 0; c < cols; c++)
- {
- /* float m = sqrt(pow(r - center.y, 2.0) + pow(c - center.x, 2.0));
- float n = m / radius;
- float o = pow(n,2*n);
- float s = 1.0 + o;
- float i = 1.0 / s;*/
- ilpFilter.at<float>(r, c) = float(1.0 / (1.0 + (pow(sqrt(pow(r - center.y, 2.0) + pow(c - center.x, 2.0)) / radius, 2 * n))));
-
- }
- }
- }
- // 高斯滤波
- else if (type == GLPFILTER)
- {
- for (int r = 0; r < rows; r++)
- {
- for (int c = 0; c < cols; c++)
- {
- ilpFilter.at<float>(r, c) = float(exp(-(pow(c-center.x,2.0)+pow(r-center.y,2.0))/(2*pow(radius,2.0))));
- }
- }
- }
- return ilpFilter;
- }
-
- Mat src;// 输入的图像
- Mat F;// 图像的快速傅里叶变换
- Point maxLocation;//傅里叶谱的最大值的坐标
- int radius = 20; // 截断频率
- const int max_Radius = 100;// 最大截断频率
-
-
-
- Mat ilpFilter;//低通滤波器
- int filterType=0;//
- int max_FilterType = 2;
-
-
- Mat F_ilpFilter;// 低通傅里叶变换
- Mat FlpSpetrum;// 低通傅里叶变换的傅里叶谱的灰度级
-
- Mat result;// 滤波后的图像
-
- string lpFilterSpectrum = "低通傅里叶谱";//
-
-
-
-
- void callback_lpFilter(int ,void *);
-
-
- int main()
- {
- src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\611.png",CV_LOAD_IMAGE_GRAYSCALE);
- if (!src.data)
- {
- cout << "原始图读取失败" << endl;
- return -1;
- }
- imshow("原图",src);
- // 数据转换 将数据转换为double
- Mat f1;
- src.convertTo(f1,CV_32FC1,1.0,0.0);
- // 2 每个数 x pow(-1,c+r);
- for (int r = 0; r < f1.rows; r++)
- {
- for (int c = 0; c < f1.cols; c++)
- {
- // 判断奇偶
- if (r+c%2)
- {
- f1.at<float>(r, c) *= -1;
- }
- }
- }
-
- // 开始傅里叶变换
- fft2Image(f1,F);// F 就是傅里叶变换之后的
-
- Mat as;
- //得到傅里叶谱
- amplitudeSpectrum(F,as);
-
- //傅里叶谱的灰度级显示
- Mat s = graySpectrum(as);
- imshow("原傅里叶谱的灰度级显示",s);
-
- // 找到傅里叶谱的最大值的坐标
- minMaxLoc(s,NULL,NULL,NULL,&maxLocation);
-
- //------------------------------------ 低通滤波----------------------------------------------
- namedWindow(lpFilterSpectrum,WINDOW_AUTOSIZE);
- createTrackbar("低通滤波:", lpFilterSpectrum,&filterType, max_FilterType, callback_lpFilter);
- createTrackbar("半径:", lpFilterSpectrum, &radius, max_Radius, callback_lpFilter);
- callback_lpFilter(0,0);
- waitKey(0);
-
- return 0;
- }
- // 回调函数
- void callback_lpFilter(int, void*)
- {
- // ----------------- 构建低通滤波器----------------------------------
- ilpFilter = createFilter(F.size(),maxLocation,radius, filterType,2);
- // -------------------- 低通滤波器和图像的傅里叶变换开始点乘=====================================
- F_ilpFilter.create(F.size(),F.type());
-
-
- for (int r = 0; r < F_ilpFilter.rows; r++)
- {
- for (int c = 0; c < F_ilpFilter.cols; c++)
- {
- // 分别取出当前位置的快速傅里叶变换和理想低通滤波的值
- Vec2f f_rc = F.at<Vec2f>(r,c);
- float lpFilter_rc = ilpFilter.at<float>(r,c);
- // 低通滤波器和图像的快速傅里叶变换的对应位置相乘
- F_ilpFilter.at<Vec2f>(r, c) = f_rc * lpFilter_rc;
- }
- }
-
- // 低通傅里叶变换的傅里叶谱
- amplitudeSpectrum(F_ilpFilter, FlpSpetrum);
-
- FlpSpetrum = graySpectrum(FlpSpetrum);
- imshow(lpFilterSpectrum, FlpSpetrum);
-
-
-
- // 对傅里叶变换逆变换 并且只要实部
- dft(F_ilpFilter,result,DFT_SCALE+DFT_INVERSE+DFT_REAL_OUTPUT);
-
-
- // 乘以 (-1)的(r+c)次方
- for (int r = 0; r < result.rows; r++)
- {
- for (int c = 0; c < result.cols; c++)
- {
- if ((c + r) % 2) result.at<float>(r, c) *= -1;
- }
- }
-
- // 很重要的一步 将结果转换成 CV_8u
- result.convertTo(result, CV_8UC1, 1.0, 0);
- result = result(Rect(0,0,src.cols,src.rows)).clone();
- imshow("经过低通滤波后的图像",result);
-
- }
- #endif
1、 理想高通滤波
2. 巴特沃斯高通滤波器
3. 高斯高通滤波器
2. 巴特沃斯带通滤波器和巴特沃斯带阻滤波器
3. 高斯带通滤波器和高斯带阻滤波器
带阻滤波器和这个上述的恰好相反
-
- #if 1 //自定义滤波器
-
- Mat image;// 输入的图像
- Mat ImageFFT;// 图像的快速傅里叶变换
- Point maxLocation;//傅里叶谱的最大值的坐标
-
-
-
- Mat ilpFilter;//低通滤波器
-
-
- Mat F_ImageSpetrum;// 傅里叶变换的傅里叶谱
-
- Mat result;// 滤波后的图像
-
- string windowName = "傅里叶幅度谱的灰度级";//
-
- bool drawing_box = false;// 鼠标事件
-
- Point drawPoint;
- Rect rectFilter;
- bool gotRectFilter = false;
-
- void mouseRectHandler(int event,int x,int y,int,void* )
- {
- switch (event)
- {
- case CV_EVENT_LBUTTONDOWN:// 鼠标按下
- drawing_box = true;
- // 记录起点
- drawPoint = Point(x, y);
- break;
- case CV_EVENT_MOUSEMOVE:
- if (drawing_box)
- {
- // 将鼠标移动到右下角
- if (x> drawPoint.x&&y>= drawPoint.y)
- {
- rectFilter.x = drawPoint.x;
- rectFilter.y = drawPoint.y;
- rectFilter.width = x - drawPoint.x;
- rectFilter.height= y - drawPoint.y;
- }
-
- // 将鼠标移动到有右上角
- if (x >= drawPoint.x && y <= drawPoint.y)
- {
- rectFilter.x = drawPoint.x;
- rectFilter.y = y;
- rectFilter.width = x - drawPoint.x;
- rectFilter.height = drawPoint.y- y ;
- }
-
- // 将鼠标移动到有左上角
- if (x >= drawPoint.x && y <= drawPoint.y)
- {
- rectFilter.x = x;
- rectFilter.y = y;
- rectFilter.width = drawPoint.x - x;
- rectFilter.height = drawPoint.y - y;
- }
-
- // 将鼠标移动到有左下角
- if (x >= drawPoint.x && y <= drawPoint.y)
- {
- rectFilter.x = x;
- rectFilter.y = drawPoint.y;
- rectFilter.width = drawPoint.x-x;
- rectFilter.height = y- drawPoint.y ;
- }
- }
- break;
- case CV_EVENT_LBUTTONUP:
- drawing_box = false;
- gotRectFilter = true;
- break;
- default:
- break;
- }
- }
-
-
- int main()
- {
- image = imread("C:\\Users\\19473\\Desktop\\opencv_images\\612.png",CV_LOAD_IMAGE_GRAYSCALE);
- if (!image.data)
- {
- cout << "原始图读取失败" << endl;
- return -1;
- }
- imshow("原图", image);
- // 数据转换 将数据转换为double
- Mat f1;
- image.convertTo(f1,CV_32FC1,1.0,0.0);
- // 2 每个数 x pow(-1,c+r);
- for (int r = 0; r < f1.rows; r++)
- {
- for (int c = 0; c < f1.cols; c++)
- {
- // 判断奇偶
- if (r+c%2)
- {
- f1.at<float>(r, c) *= -1;
- }
- }
- }
-
- // 开始傅里叶变换
- fft2Image(f1,ImageFFT);// F 就是傅里叶变换之后的
-
- Mat amplSpec;
- //得到傅里叶谱
- amplitudeSpectrum(ImageFFT, amplSpec);
-
- //傅里叶谱的灰度级显示
- Mat spectrum = graySpectrum(amplSpec);
-
-
- // 找到傅里叶谱的最大值的坐标
- minMaxLoc(amplSpec,NULL,NULL,NULL,&maxLocation);
-
- //------------------------------------ 自定义 滤波----------------------------------------------
- namedWindow(windowName,WINDOW_AUTOSIZE);
-
- setMouseCallback(windowName, mouseRectHandler,NULL);
- for (;;)
- {
-
- spectrum(rectFilter).setTo(0);
- // 自定义 滤波器和傅里叶变换点乘
- ImageFFT(rectFilter).setTo(Scalar::all(0));
- imshow(windowName, spectrum);
- // 按esc 见退出编辑
- if (waitKey(10)==27)
- {
- break;
- }
-
- }
-
- Mat result;
-
- // 对傅里叶变换逆变换 并且只要实部
- dft(ImageFFT, result, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT);
-
-
- // 乘以 (-1)的(r+c)次方
- for (int r = 0; r < result.rows; r++)
- {
- for (int c = 0; c < result.cols; c++)
- {
- if ((c + r) % 2) result.at<float>(r, c) *= -1;
- }
- }
-
- // 很重要的一步 将结果转换成 CV_8u
- result.convertTo(result, CV_8UC1, 1.0, 0);
- result = result(Rect(0, 0, image.cols, image.rows)).clone();
- imshow("经过自定义滤波后的图像", result);
- waitKey(0);
-
- return 0;
- }
- // 回调函数
-
- #endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。