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

  • 图像降噪算法——高斯低通滤波
    • 1. 基本原理
    • 2. C++代码实现
    • 3. 结论

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

1. 基本原理

通过离散傅里叶变换对图像进行滤波流程作非常简单,就如下图所示:

(1) 二维离散傅里叶变换的公式为:F(u,v)=∑x=0M−1∑y=0N−1f(x,y)e−j2π(ux/M+vy/N)F(u, v)=\sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x, y) \mathrm{e}^{-\mathrm{j} 2 \pi(u x / M+v y / N)}F(u,v)=x=0∑M−1​y=0∑N−1​f(x,y)e−j2π(ux/M+vy/N)其中,xxx和yyy分别为原始图像上的横纵坐标,MMM和NNN为为原始图像的高和宽,f(x,y)f(x,y)f(x,y)为原始图像上坐标(x,y)(x,y)(x,y)处的灰度值,其中,根据欧拉公式:e−j2π(ux/M+vy/N)=cos(2π(uxM+vyN))−jsin(2π(uxM+vyN))\mathrm{e}^{-\mathrm{j} 2 \pi(u x / M+v y / N)}=cos(2 \pi(\frac{u x} {M}+\frac{v y}{N}))-jsin(2 \pi(\frac{u x} {M}+\frac{v y}{N}))e−j2π(ux/M+vy/N)=cos(2π(Mux​+Nvy​))−jsin(2π(Mux​+Nvy​))因此原始图像通过二维离散傅里叶变换获得的二维频谱上每一个像素都是复数,在OpenCV中用Mat数据格式处理时,每个像素值都有两个通道。

(2) 二维离散傅里叶反变换的公式为:f(x,y)=1MN∑u=0M−1∑v=0N−1F(u,v)ej2π(ux/M+vy/N)f(x, y)=\frac{1}{M N} \sum_{u=0}^{M-1} \sum_{v=0}^{N-1} F(u, v) \mathrm{e}^{\mathrm{j} 2 \pi(u x / M+v y / N)}f(x,y)=MN1​u=0∑M−1​v=0∑N−1​F(u,v)ej2π(ux/M+vy/N)其中,符号表示和上述二维离散傅里叶变换相同。

(3) 对二维频谱的各种操作的具体方式:将二维频谱与设计好的滤波模板进行乘积,为什么是乘积呢?

因为根据傅里叶变换的性质,频率域中的乘积相当于空间域中的卷积,即f(x,y)⋆h(x,y)⇔F(u,v)H(u,v)f(x, y) \star h(x, y) \Leftrightarrow F(u, v) H(u, v)f(x,y)⋆h(x,y)⇔F(u,v)H(u,v),其中二维循环卷积公式如下f(x,y)⋆h(x,y)=∑m=0M−1∑n=0N−1f(m,n)h(x−m,y−n)f(x, y) \star h(x, y)=\sum_{m=0}^{M-1} \sum_{n=0}^{N-1} f(m, n) h(x-m, y-n)f(x,y)⋆h(x,y)=m=0∑M−1​n=0∑N−1​f(m,n)h(x−m,y−n)以高斯低通滤波为例,即H(u,v)=e−D2(u,v)/2σ2H(u, v)=\mathrm{e}^{-D^{2}(u, v) / 2 \sigma^{2}}H(u,v)=e−D2(u,v)/2σ2其中D(u,v)D(u,v)D(u,v)为二维频谱上像素(u,v)(u,v)(u,v)距离中心的距离,其通过傅里叶反变换得到:h(x,y)=2πσe−2π2σ2D2(x,y)h(x,y)=\sqrt{2 \pi} \sigma \mathrm{e}^{-2 \pi^{2} \sigma^{2} D^{2}(x,y)}h(x,y)=2π​σe−2π2σ2D2(x,y)其中D(x,y)D(x,y)D(x,y)为空间域图像上像素(x,y)(x,y)(x,y)距离中心的距离。可以发现空间域中同样是一个高斯滤波器,两者之间的关系是频率中高斯低通滤波器越窄,说明其衰减的低频越多,引起的模糊就越大,在空间域中就相当于使用了更大的模板来增加模糊。

2. C++代码实现

下面是基于OpenCV实现的频域的高斯低通滤波器

//高斯低通滤波器(频域)
Mat Denoise::GaussianLowPassFilter(const Mat &src, double sigma)
{//这些图片是过程中会用到的,pad是原图像0填充后的图像,cpx是双通道频域图,mag是频域幅值图,dst是滤波后的图像Mat pad, cpx, mag, dst;//获取傅里叶变化最佳图片尺寸,为2的指数int m = getOptimalDFTSize(src.rows);int n = getOptimalDFTSize(src.cols);//对原始图片用0进行填充获得最佳尺寸图片copyMakeBorder(src, pad, 0, m-src.rows, 0, n-src.cols, BORDER_CONSTANT, Scalar::all(0));//生成高斯模板Mat gaussian(pad.size(),CV_32FC2);for(int i = 0; i<m; i++){float* p = gaussian.ptr<float>(i);for(int j = 0; j<n; j++){double d = pow(i-m/2, 2) + pow(j-n/2, 2);p[2*j] = expf(-d/sigma/sigma/2.0);p[2*j+1] = expf(-d/sigma/sigma/2.0);}}//建立双通道图片,其中planes[0]填充原始图片Mat planes[] = {Mat_<float>(pad), Mat::zeros(pad.size(), CV_32F)};merge(planes, 2, cpx);//进行傅里叶变换dft(cpx, cpx);//分离通道并进行象限变幻split(cpx, planes);planes[0] = ShiftQuadrant(planes[0]);planes[1] = ShiftQuadrant(planes[1]);
//    magnitude(planes[0], planes[1], mag);
//    mag += Scalar::all(1);
//    log(mag, mag);
//    normalize(mag, mag, 0, 1, CV_MINMAX);
//    imshow("mag1", mag);//进行滤波merge(planes, 2, cpx);multiply(cpx, gaussian, cpx);//分离通道并进行象限变幻split(cpx, planes);//计算幅值,并讲幅值存储再planes[0]中magnitude(planes[0], planes[1], mag);
//    mag += Scalar::all(1);
//    log(mag, mag);
//    normalize(mag, mag, 0, 1, CV_MINMAX);
//    imshow("mag2", mag);planes[0] = ShiftQuadrant(planes[0]);planes[1] = ShiftQuadrant(planes[1]);//重新合并实部planes[0]和虚部planes[1]merge(planes, 2, cpx);//进行反傅里叶变换idft(cpx, dst, DFT_SCALE | DFT_REAL_OUTPUT);dst.convertTo(dst, CV_8UC1);return dst;
}Mat Denoise::ShiftQuadrant(const Mat &src)
{// 交换前// ×××××××××××××××××××××××// ×    q1    ×    q2    ×// ×          ×          ×// ×××××××××××××××××××××××// ×    q3    ×    q4    ×// ×          ×          ×// ×××××××××××××××××××××××// 交换后// ×××××××××××××××××××××××// ×    q4    ×    q3    ×// ×          ×          ×// ×××××××××××××××××××××××// ×    q2    ×    q1    ×// ×          ×          ×// ×××××××××××××××××××××××Mat dst = src.clone();int m = src.rows, n = src.cols;Mat q1(dst, Rect(0,0,n/2,m/2));Mat q2(dst, Rect(n/2,0,n/2,m/2));Mat q3(dst, Rect(0,m/2,n/2,m/2));Mat q4(dst, Rect(n/2,m/2,n/2,m/2));//交换象限Mat temp;q1.copyTo(temp);q4.copyTo(q1);temp.copyTo(q4);q2.copyTo(temp);q3.copyTo(q2);temp.copyTo(q3);return dst;
}

下面是运行结果:
首先,下面这是原图:

添加上高斯噪声后:
进行二维离散傅里叶变换获得二维频谱(下面显示的幅值图mag,仅仅是为了演示频域滤波的过程,实际上用来操作的是两通道的频谱图cpx):

对二维频谱进行操作,乘以高斯低通滤波器:

最后通过二维离散傅里叶反变换获得降噪图像:

3. 结论

  1. 本文是直接上手二维离散傅里叶变换进行滤波,啥是离散傅里叶变换?怎么就变换了?不太熟悉的同学建议复习下《数字信号处理》或者到网上看一些大佬的博客,这里推荐几篇:
    1. 从菜鸟到完全学会二维傅立叶在图像处理算法中的应用【老司机教你学傅立叶】
    2. 为什么用图像二维傅里叶变换的相位谱进行反变换,能够大致得到原图的形状,而幅度谱则不行呢?
    3. 十分简明易懂的FFT(快速傅里叶变换)
    4. 如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧

  2. 本文介绍的二维离散傅里叶变换是最基本的形式,而实际应用中采用的肯定是快速傅里叶变换。

  3. 采用离散傅里叶进行滤波会有更直观,但是由于空间域可以进行并行计算,因此实际滤波是还是更加倾向于空间域滤波。

暂时分享这么多,有问题欢迎交流~
此外,这里我写一个各种算法的总结目录图像降噪算法——图像降噪算法总结,对图像降噪算法感兴趣的同学欢迎参考

图像降噪算法——高斯低通滤波相关推荐

  1. 读入一幅图像,对图像分别进行高斯低通、巴特沃兹低通、高斯高通和巴特沃兹高通频域滤波,比较其锐化和平滑效果。

    ↵ 1.高斯低通 二维高斯低通滤波器定义如下: D0为截止频率与原点的距离,D(u,v)是点(u,v)与原点的距离. 图像表示: 读入图片并得到频谱图,后续搭建高斯低通滤波器如下. [m,n]=siz ...

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

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

  3. MATLAB高斯低通滤波图像

    clc,clear,close all % 清理命令区.清理工作区.关闭显示图形 warning off % 消除警告 feature jit off % 加速代码运行 D0 = 20; % 阻止的频 ...

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

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

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

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

  6. python高通滤波器设计_python实现直方图均衡化,理想高通滤波与高斯低通滤波

    写在前面 HIT大三上学期视听觉信号处理课程中视觉部分的实验二,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验二. 由于时间紧张,代码没有进行任何优化, ...

  7. python高通滤波_python实现直方图均衡化,理想高通滤波与高斯低通滤波

    写在前面 HIT大三上学期视听觉信号处理课程中视觉部分的实验二,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验二. 由于时间紧张,代码没有进行任何优化, ...

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

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

  9. MATLAB图像处理--高斯低通滤波、高斯高通滤波(代码及示例)

    本文目录 常用的滤波器 高斯低通滤波器 matlab代码 高斯高通滤波器 Butterworth 低通滤波器 常用的滤波器 常用的滤波器有以下几种: 频域滤波器 频域平滑滤波器 理想低通滤波器 巴特沃 ...

最新文章

  1. LabVIEW图像灰度测量(基础篇—7)
  2. pika主从同步原理
  3. c++重载后置++和--
  4. js阻止ajax继续请求,js 拦截全局 ajax 请求
  5. win10如何换pip源
  6. 联想rd650怎么装系统win7_Lenovo g50重装win7系统|U盘重装联想g50笔记本系统
  7. SynchronizationContext(同步上下文)综述
  8. easyui控件事件监听委托给jquery事件监听,keyup取最新值问题
  9. Ubuntu图形化数据库连接工具
  10. 黑马程序员顺义校区php_2018黑马整套php视频教程
  11. 刷机-升级到3.80M33的方法
  12. 系统论的应用——心理学
  13. 【转】Ogre 1.7版本重大改进by 诡辩
  14. 基于servlet+jsp 个人博客系统
  15. win10无限蓝屏_Win10升级系统后蓝屏或无限重启解决办法
  16. 正则表达式匹配从指定字符开始到指定字符结束的字符串
  17. 神经网络模型的模型假设,神经网络模型预测控制
  18. 战地4稳定的服务器,战地4 游戏服务器
  19. 【Spark亚太研究院系列丛书】Spark实战高手之路-第2章动手实战Scala第3小节(2)
  20. ACM-ICPC2014北京邀请赛感受

热门文章

  1. oracle ipc message,【案例】Oracle RAC IPC send timeout error导致RAC的节点挂起解决办法
  2. 【数据结构-查找】3.散列表详解
  3. 太火了!MyBatis Plus 为啥这么牛?
  4. Java设计模式-适配器模式Adapter
  5. BigDecimal add方法问题:调用add后,求和结果没变
  6. Java中IO流的总结
  7. 跳表(SkipList)设计与实现(java)
  8. Activiti工作流之流程变量
  9. 派生类的构造【C++继承】
  10. linux shell获取字符串第1个字符