最近由于作业原因,试着用OpenCV实现频率域滤波,但是OpenCV中并没有像MATLAB中fftshift这样的中心化操作,所以我写了一个频率域滤波的函数,以后用频率域滤波的时候在主函数中调用即可。当然,水平有限,编写的代码并不优美,有问题请大家留言批评指正。

在这里我不介绍傅里叶变换,频率域滤波和高斯低通滤波器的原理,想必大家已经有了大概了解,本文关注于OpenCV中的代码实现。

废话少说,先上一张例图:

这幅图像的噪声为周期性噪声,带用阻滤波器或者陷波滤波器去噪较好,这里用高斯低通去噪,效果一般,周期性没有完全去除。

下面是频率域滤波的流程

1、计算原图像的DFT,得到F(U,V);

2、将频谱F(U,V)的零频点移到中心位置;

3、计算滤波器函数H(U,V)与上步结果F(U,V)的乘积G(U,V);

4、将上一步结果G(U,V)的零频点移回;(在OpenCV中没有这步也没关系,原因待解)

5、计算上步的IDFT,得到g(X,Y);

6、取g(X,Y)的模作为结果。

下面根据上述步骤编写代码如下:

//**************************************
//频率域滤波——以高斯低通为例
//**************************************
#include<opencv2/opencv.hpp>
#include<iostream>using namespace std;
using namespace cv;
Mat gaussianlbrf(Mat scr,float sigma);//高斯低通滤波器函数
Mat freqfilt(Mat scr,Mat blur);//频率域滤波函数int main()
{Mat input=imread("imageHill.jpg",CV_LOAD_IMAGE_GRAYSCALE);imshow("原图",input);int w=getOptimalDFTSize(input.cols);  //获取进行dtf的最优尺寸int h=getOptimalDFTSize(input.rows); //获取进行dtf的最优尺寸Mat padded;  copyMakeBorder(input,padded,0,h-input.rows,0,w-input.cols,  BORDER_CONSTANT  , Scalar::all(0));  //边界填充padded.convertTo(padded,CV_32FC1); //将图像转换为flaot型Mat gaussianKernel=gaussianlbrf(padded,45);//高斯低通滤波器Mat out=freqfilt(padded,gaussianKernel);//频率域滤波imshow("结果图 sigma=40",out);waitKey(0);return 0;
}//*****************高斯低通滤波器***********************
Mat gaussianlbrf(Mat scr,float sigma)
{Mat gaussianBlur(scr.size(),CV_32FC1); //,CV_32FC1float d0=2*sigma*sigma;//高斯函数参数,越小,频率高斯滤波器越窄,滤除高频成分越多,图像就越平滑for(int i=0;i<scr.rows ; i++ ){for(int j=0; j<scr.cols ; j++ ){float d=pow(float(i-scr.rows/2),2)+pow(float(j-scr.cols/2),2);//分子,计算pow必须为float型gaussianBlur.at<float>(i,j)=expf(-d/d0);//expf为以e为底求幂(必须为float型)}}imshow("高斯低通滤波器",gaussianBlur);return gaussianBlur;
}//*****************频率域滤波*******************
Mat freqfilt(Mat scr,Mat blur)
{//***********************DFT*******************Mat plane[]={scr, Mat::zeros(scr.size() , CV_32FC1)}; //创建通道,存储dft后的实部与虚部(CV_32F,必须为单通道数)Mat complexIm;  merge(plane,2,complexIm);//合并通道 (把两个矩阵合并为一个2通道的Mat类容器)dft(complexIm,complexIm);//进行傅立叶变换,结果保存在自身  //***************中心化********************split(complexIm,plane);//分离通道(数组分离)int cx=plane[0].cols/2;int cy=plane[0].rows/2;//以下的操作是移动图像  (零频移到中心)Mat part1_r(plane[0],Rect(0,0,cx,cy));  //元素坐标表示为(cx,cy)Mat part2_r(plane[0],Rect(cx,0,cx,cy));  Mat part3_r(plane[0],Rect(0,cy,cx,cy));  Mat part4_r(plane[0],Rect(cx,cy,cx,cy));  Mat temp; part1_r.copyTo(temp);  //左上与右下交换位置(实部)part4_r.copyTo(part1_r);  temp.copyTo(part4_r);  part2_r.copyTo(temp);  //右上与左下交换位置(实部)part3_r.copyTo(part2_r);  temp.copyTo(part3_r);Mat part1_i(plane[1],Rect(0,0,cx,cy));  //元素坐标(cx,cy)Mat part2_i(plane[1],Rect(cx,0,cx,cy));  Mat part3_i(plane[1],Rect(0,cy,cx,cy));  Mat part4_i(plane[1],Rect(cx,cy,cx,cy));  part1_i.copyTo(temp);  //左上与右下交换位置(虚部)part4_i.copyTo(part1_i);  temp.copyTo(part4_i);  part2_i.copyTo(temp);  //右上与左下交换位置(虚部)part3_i.copyTo(part2_i);  temp.copyTo(part3_i);//*****************滤波器函数与DFT结果的乘积****************Mat blur_r,blur_i,BLUR;  multiply(plane[0], blur, blur_r); //滤波(实部与滤波器模板对应元素相乘)multiply(plane[1], blur,blur_i);//滤波(虚部与滤波器模板对应元素相乘)Mat plane1[]={blur_r, blur_i};merge(plane1,2,BLUR);//实部与虚部合并//*********************得到原图频谱图***********************************magnitude(plane[0],plane[1],plane[0]);//获取幅度图像,0通道为实部通道,1为虚部,因为二维傅立叶变换结果是复数  plane[0]+=Scalar::all(1);  //傅立叶变o换后的图片不好分析,进行对数处理,结果比较好看 log(plane[0],plane[0]);    // float型的灰度空间为[0,1])normalize(plane[0],plane[0],1,0,CV_MINMAX);  //归一化便于显示imshow("原图像频谱图",plane[0]);  //******************IDFT*******************************/*Mat part111(BLUR,Rect(0,0,cx,cy));  //元素坐标(cx,cy)Mat part222(BLUR,Rect(cx,0,cx,cy));  Mat part333(BLUR,Rect(0,cy,cx,cy));  Mat part444(BLUR,Rect(cx,cy,cx,cy));  part111.copyTo(temp);  //左上与右下交换位置(虚部)part444.copyTo(part111);  temp.copyTo(part444);  part222.copyTo(temp);  //右上与左下交换位置part333.copyTo(part222);  temp.copyTo(part333);*/idft( BLUR, BLUR);  //idft结果也为复数split(BLUR,plane);//分离通道,主要获取通道magnitude(plane[0],plane[1],plane[0]);  //求幅值(模)normalize(plane[0],plane[0],1,0,CV_MINMAX);  //归一化便于显示return plane[0];//返回参数
}

效果图:

注:1,结果的黑边为填充效果。

2,务必注意矩阵数据类型,做DFT,必须为浮点型,计算滤波器函数H(U,V)与DFT的乘积G(U,V)时,数据类型务必一致,包括通道数,单通道类型不能与多通道类型相乘,关于数据类型,可以参看这里。

参考:https://blog.csdn.net/dang_boy/article/details/76150067

OpenCV实现频率域滤波——以高斯低通滤波去噪为例相关推荐

  1. python理想低通滤波、巴特沃斯低通滤波、高斯低通滤波实现

    代码 代码如下(示例): import numpy as np import cv2 as cv image = cv.imread('2.PNG') # print(image.shape) ima ...

  2. 用matlab编程实现数字图像理想低通滤波、高斯低通滤波和巴特沃斯低通滤波去噪算法

    1 理想低通滤波 %理想低通 I = imread('fig.png'); I=rgb2gray(I); figure(1); subplot(221),imshow(I); title('原图像') ...

  3. Opencv学习笔记 各向异性滤波/均值滤波/高斯滤波/中值滤波/加权中值滤波/高斯低通滤波

    各向异性滤波         各向异性扩散滤波主要是用来平滑图像的,克服了高斯模糊的缺陷,各向异性扩散在平滑图像时是保留图像边缘的,和双边滤波很像. public static void ImageA ...

  4. 图像的频率域高斯低通滤波

    (1)自定义一个图像的频率域高斯低通滤波处理函数,要求该函数的输入参数包括处理前的图像ima和距频率矩形中心的距离D0(截止频率),输出参数为滤波处理后的图像im2. 自定义的高斯低通滤波器: %ph ...

  5. c++ opencv数字图像处理:频率域滤波--低通滤波--巴特沃斯低通滤波

    文章目录 前言 一.巴特沃斯低通滤波器(BLPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯低通滤波器(BLPF) D2( ...

  6. 图像算法四:【图像增强--频率域】傅里叶变换、快速傅里叶变换、频域滤波、频域低通滤波、频域高通滤波

    频率域滤波与空间域滤波殊途同归,空间域图像增强与频率域图像增强是两种截然不同的技术,实际上在相当程度上说它们是在不同的领域做相同的事情,只是有些滤波更适合在空间域完成,而有些则更适合在频率域中完成. ...

  7. 数字图像处理 空间域高斯低通滤波 MATLAB实验

    一.原理_空间域高斯低通滤波 高斯低通滤波是一种使用的去噪滤波,可用于去除高斯噪声,且几乎没有振铃现象. 二.步骤 (1)读入原图像lena.bmp并显示: (2)对原图像分别添加高斯噪声,并显示加噪 ...

  8. 图像降噪算法——高斯低通滤波

    图像降噪算法--高斯低通滤波 图像降噪算法--高斯低通滤波 1. 基本原理 2. C++代码实现 3. 结论 图像降噪算法--高斯低通滤波 1. 基本原理 通过离散傅里叶变换对图像进行滤波流程作非常简 ...

  9. OPENCV计算机视觉图像处理频域傅里叶 DFT 变换低通滤波逆变换IDFT

    OpenCV计算机视觉图像频域傅里叶 DFT 变换低通滤波逆变换IDFT 实验室做图像的,经常用到这部分,为了检测屏幕,看过好多博客,试用过许多代码,这个算是我找到的比较好用的,也容易改. 傅里叶变换 ...

最新文章

  1. OpenCV基础知识入门
  2. mysql udf http.so_MySQL-UDF-HTTP + Express + WebSocket 实现数据库推送
  3. vs2010安装AnkhSVN,但是不起作用解决方法
  4. H.264视频RTP负载格式/NALU的类型
  5. 谈谈NLP下一个主战场:万亿参数的预训练模型!
  6. websocket底层处理粘包_Socket解决粘包问题1
  7. HashiCorp Vault 1.0开源自动解封特性,新增Batch令牌
  8. java如何查内存泄露_如何排查Java内存泄露
  9. 首页css命名,常用的CSS命名规则
  10. 网页在ie内核的浏览器下面整体偏左
  11. 数字图像处理实验(九):meanshift跟踪算法
  12. 数学建模神经网络模型,数学建模神经网络算法
  13. 休息休闲推荐 ---- 电视剧《觉醒年代》百年优秀历史纪录电视剧
  14. 我与 SAP 成都研究院吴院长的二三事
  15. 南非SABS EMC CoC简介
  16. HTML设置页面动画效果有几种,前端制作动画的几种方式(css3,js)
  17. matlab使用出现矩阵为奇异值、接近奇异值或缩放错误。结果可能不准确。RCOND = NaN。
  18. RTX3060是什么级别显卡 RTX3060显卡什么水平
  19. 命令行——rm命令(删除)详解
  20. 统计分析html,统计分析—月计划指标汇总.html

热门文章

  1. key存在则更新,不存在则插入
  2. 重庆宽带公网IPv6测试
  3. PWN lotto [pwnable.kr]CTF writeup题解系列10
  4. 为什么二进制无法精确表达部分十进制的小数
  5. java判断标点符号问题
  6. 1、了解网站建设原理
  7. Redis安装配置操作
  8. 202105面试总结-4
  9. 浏览器打开收藏夹中书签的各种方法
  10. pairwise损失_triplet损失_提升精排模型的trick