前言

无意中看到了一篇比较老的论文,Adaptive median filters: new algorithms and results。感兴趣的可以下载下来看看。主要就是提出了一种自适应中值滤波算法,这个算法是很经典的中值滤波算法的改进版本,自动选择滤波器的大小,以追求更好的效果。原理十分简单,后面都尽量简短地进行说明。

中值滤波器(Median Filter)

中值滤波的思想就是比较一定领域内的像素值的大小,取出其中值作为这个领域的中心像素新的值。假设对一定领域内的所有像素从小到大进行排序,如果存在孤立的噪声点,比如椒盐噪声(椒噪声——较小的灰度值,呈现的效果是小黑点;盐噪声——较大的灰度值,呈现的效果是小白点),那么从小到大排序的这个数组中,那些孤立的噪声一定会分布在两边(要么很小,要么很大),这样子取出的中值点可以很好地保留像素信息,而滤除了噪声点的影响。
中值滤波器受滤波窗口大小影响较大,用于消除噪声和保护图像细节,两者会存在冲突。如果窗口较小,则能较好地保护图像中的一些细节信息,但对噪声的过滤效果就会打折扣;反之,如果窗口尺寸较大则会有较好的噪声过滤效果,但也会对图像造成一定的模糊效果,从而丢失一部分细节信息。另外,如果在滤波窗口内的噪声点的个数大于整个窗口内像素的个数,则中值滤波就不能很好的过滤掉噪声。

自适应中值滤波器(Adaptive Median Filter)

在噪声密度不是很大的情况下(根据经验,噪声的出现的概率小于0.2),使用中值滤波的效果不错。但是当噪声出现的概率比较高时,原来的中值滤波算法就不是很有效了。只有增大滤波器窗口尺寸,尽管会使图像变得模糊。
使用自适应中值滤波器的目的就是,根据预设好的条件,动态地改变中值滤波器的窗口尺寸,以同时兼顾去噪声作用和保护细节的效果。
下面是自适应中值滤波器算法的详细描述:
预先定义好以下符号:

  • SxySxyS_{xy}:滤波器的作用区域,滤波器窗口所覆盖的区域,该区域中心点为图像中第y行第x列个像素点;
  • ZminZminZ_{min}:SxySxyS_{xy}中最小的灰度值;
  • ZmaxZmaxZ_{max}:SxySxyS_{xy}中最大的灰度值;
  • ZmedZmedZ_{med}:SxySxyS_{xy}中所有灰度值的中值;
  • ZxyZxyZ_{xy}:表示图像中第y行第x列个像素点的灰度值;
  • SmaxSmaxS_{max}:SxySxyS_{xy}所允许的最大窗口尺寸;

自适应中值滤波器分为以下两个过程,AB
A:
1. A1 = ZmedZmedZ_{med} - ZminZminZ_{min}
2. A2 = ZmedZmedZ_{med} - ZmaxZmaxZ_{max}
3. 如果A1>0A1>0A1 > 0 且 A2<0A2<0A2 ,则跳转到B
4. 否则,增大窗口的尺寸
5. 如果增大后的尺寸≤≤\leqSmaxSmaxS_{max},则重复A
6. 否则,直接输出ZmedZmedZ_{med}
B
1. B1 = ZxyZxyZ_{xy} - ZminZminZ_{min}
2. B2 = ZxyZxyZ_{xy} - ZmaxZmaxZ_{max}
3. 如果B1>0B1>0B1 > 0 且 B2<0B2<0B2 ,则输出ZxyZxyZ_{xy}
4. 否则输出ZmedZmedZ_{med}

直观解释

在自适应中值滤波算法中,A步骤里面会先判断是否满足Zmin<Zmed<ZmaxZmin<Zmed<ZmaxZ_{min} 。这一步骤实质是判断当前区域的中值点是否是噪声点,通常来说是满足Zmin<Zmed<ZmaxZmin<Zmed<ZmaxZ_{min} 这个条件的,此时中值点不是噪声点,跳转到B;考虑一些特殊情况,如果Zmed=ZminZmed=ZminZ_{med}=Z_{min}或者Zmed=ZmaxZmed=ZmaxZ_{med}=Z_{max},则认为是噪声点,应该扩大窗口尺寸,在一个更大的范围内寻找一个合适的非噪声点,随后再跳转到B,否则输出的中值点是噪声点;
接下来考虑跳转到B之后的情况:判断中心点的像素值是否是噪声点,判断条件为Zmin<Zxy<ZmaxZmin<Zxy<ZmaxZ_{min} ,原理同上,因为如果Zxy=ZminZxy=ZminZ_{xy}=Z_{min}或者Zxy=ZmaxZxy=ZmaxZ_{xy}=Z_{max},则认为是噪声点。如果不是噪声点,我们可以保留当前像素点的灰度值;如果是噪声点,则使用中值替代原始灰度值,滤去噪声。

程序实现

程序中定义了产生椒噪声和盐噪声函数,以及中值滤波和自适应中值滤波的函数。
程序很基础,不做赘述。

#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>//盐噪声
void saltNoise(cv::Mat img, int n)
{int x, y;for (int i = 0;i < n / 2;i++){x = std::rand() % img.cols;y = std::rand() % img.rows;if (img.type() == CV_8UC1){img.at<uchar>(y, x) = 255;}else if (img.type() == CV_8UC3){img.at<cv::Vec3b>(y, x)[0] = 255;img.at<cv::Vec3b>(y, x)[1] = 255;img.at<cv::Vec3b>(y, x)[2] = 255;}}
}//椒噪声
void pepperNoise(cv::Mat img, int n)
{int x, y;for (int i = 0;i < n / 2;i++){x = std::rand() % img.cols;y = std::rand() % img.rows;if (img.type() == CV_8UC1){img.at<uchar>(y, x) = 0;}else if (img.type() == CV_8UC3){img.at<cv::Vec3b>(y, x)[0] = 0;img.at<cv::Vec3b>(y, x)[1] = 0;img.at<cv::Vec3b>(y, x)[2] = 0;}}
}// 中值滤波器
uchar medianFilter(cv::Mat img, int row, int col, int kernelSize)
{std::vector<uchar> pixels;for (int y = -kernelSize / 2;y <= kernelSize / 2;y++){for (int x = -kernelSize / 2;x <= kernelSize / 2;x++){pixels.push_back(img.at<uchar>(row + y, col + x));}}sort(pixels.begin(), pixels.end());auto med = pixels[kernelSize*kernelSize / 2];return med;
}// 自适应中值滤波器
uchar adaptiveMedianFilter(cv::Mat &img, int row, int col, int kernelSize, int maxSize)
{std::vector<uchar> pixels;for (int y = -kernelSize / 2;y <= kernelSize / 2;y++){for (int x = -kernelSize / 2;x <= kernelSize / 2;x++){pixels.push_back(img.at<uchar>(row + y, col + x));}}sort(pixels.begin(), pixels.end());auto min = pixels[0];auto max = pixels[kernelSize*kernelSize - 1];auto med = pixels[kernelSize*kernelSize / 2];auto zxy = img.at<uchar>(row, col);if (med > min && med < max){// to Bif (zxy > min && zxy < max)return zxy;elsereturn med;}else{kernelSize += 2;if (kernelSize <= maxSize)return adaptiveMedianFilter(img, row, col, kernelSize, maxSize);// 增大窗口尺寸,继续A过程。elsereturn med;}
}int main()
{int minSize = 3;int maxSize = 7;cv::Mat img;img = cv::imread("lena.bmp");cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);cv::imshow("src", img);saltNoise(img, 40000);pepperNoise(img, 40000);cv::imshow("noise", img);cv::Mat temp = img.clone();// 自适应中值滤波cv::Mat img1;// 扩展图像的边界cv::copyMakeBorder(img, img1, maxSize / 2, maxSize / 2, maxSize / 2, maxSize / 2, cv::BorderTypes::BORDER_REFLECT);// 图像循环for (int j = maxSize / 2;j < img1.rows - maxSize / 2;j++){for (int i = maxSize / 2;i < img1.cols - maxSize / 2;i++){img1.at<uchar>(j, i) = adaptiveMedianFilter(img1, j, i, minSize, maxSize);}}cv::imshow("adaptiveMedianFilter", img1);// 中值滤波cv::Mat img2;int kernelSize = 3;cv::copyMakeBorder(temp, img2, kernelSize / 2, kernelSize / 2, kernelSize / 2, kernelSize / 2, cv::BorderTypes::BORDER_REFLECT);for (int j = kernelSize / 2;j < img2.rows - kernelSize / 2;j++){for (int i = kernelSize / 2;i < img2.cols - kernelSize / 2;i++){img2.at<uchar>(j, i) = medianFilter(img2, j, i, kernelSize);}}cv::imshow("medianFilter", img2);cv::waitKey();cv::destroyAllWindows();return 0;
}

结果截图

原始图像和添加椒盐噪声后的图像。

其实截图中看不出很明显的区别,在自己电脑上运行后看结果会清楚点。可以看到使用普通中值滤波的结果相比另一个会模糊一些,且局部仍然会有一小的噪声点。图像边缘多出来的区域不好做中值滤波处理保留了原始图像,所以边缘那一圈仍然有噪声。

自适应中值滤波及实现相关推荐

  1. matlab练习程序(自适应中值滤波RAMF)

    中值滤波是很经典的算法了.今天看论文又知道还有一种叫自适应中值滤波的算法RAMF.原论文在这里. RAMF主要通过以下两步来处理图像. 1.首先确定最大的滤波半径,然后用一个合适的半径r对图像进行滤波 ...

  2. 自适应中值滤波用于超声图像降噪

    自适应中值滤波原理: RAMF主要通过以下两步来处理图像. 1.首先确定最大的滤波半径,然后用一个合适的半径r对图像进行滤波.计算当前滤波半径像素灰度的Imin,Imax,Imed,然后判断Imed是 ...

  3. C++自定义自适应中值滤波

    Mat autoMedFilter(Mat img, int filter_size,int max_filter_size) {//滤波器尺寸必须是奇数if ((filter_size % 2) ! ...

  4. matlab中基于十字形窗口的滤波算法,#215;字形滤波窗口在Matlab自适应中值滤波算法中的应用 - 21ic中国电子网...

    由于种种原因,图像在生成.传输.变换等过程中往往会受到各种噪声的污染,从而导致图像质量退化.噪声信号的滤波是图像处理的基本任务之一,主要有线性滤波和非线性滤波两种方法.线性滤波方法一般具有低通特性,而 ...

  5. 【图像去噪】基于matlab自适应中值滤波图像去噪【含Matlab 1156期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[图像去噪]基于matlab自适应中值滤波图像去噪[含Matlab 1156期] (https://download.csdn.net/d ...

  6. 数字图像处理,自适应中值滤波的C++实现

    自适应中值滤波的原理 自适应中值滤波的思想是根据噪声密度改变滤波窗口的大小,同时对噪声点和信号点采取不同的处理方法.对噪声点进行中值滤波,对信号点保持其灰度值不变. 设为fij为点(i,j)的灰度值, ...

  7. matlab编程实现自适应均值滤波和自适应中值滤波

    matlab编程实现自适应滤波器 一.自适应均值滤波器 1. 原理部分: 2. 程序代码 3. 结果对比 二.自适应中值滤波 1. 原理部分 2.程序代码 3. 结果对比 一.自适应均值滤波器 1. ...

  8. MATLAB自编自适应中值滤波算法

    代码原理: 在噪声密度不是很大的情况下(根据经验,噪声的出现的概率小于0.2),使用中值滤波的效果不错.但是当噪声出现的概率比较高时,原来的中值滤波算法就不是很有效了.只有增大滤波器窗口尺寸,尽管会使 ...

  9. matlab设计自适应中值滤波,matlab课程设计(自适应中值滤波).doc

    matlab课程设计(自适应中值滤波).doc 10信息工程系课程设计报告课程MATLAB课程设计专业通信工程班级2级本科二班学生姓名1景学号114学生姓名2学号1414学生姓名3王学号6学生姓名4学 ...

最新文章

  1. R语言编写自定义函数基于ggsumarystats函数计算每个分组的统计值、自定义可视化分组分面条形图,并在X轴标签下方添加分组对应的统计值(样本数N、中位数median、四分位数的间距iqr)
  2. Win 10 源码一览:0.5T 代码、400 万文件、50 万文件夹
  3. 关于验证码整理的新版本
  4. oracle 创建 触发,Oracle 创建触发器
  5. matlab和python哪个运行快_MATLAB比Python更快吗?
  6. java调用net_Java调用C#.net开发的WebService
  7. 大话西游之Office应用实例系列! 13
  8. 对require四种引入方式的认识
  9. mysql update中使用subquery
  10. 【微信小程序】带你做一个公众号留言系统(附源码)
  11. 《Hadoop海量数据处理:技术详解与项目实战(第2版)》一2.8 小结
  12. Grunt Server:Fatal error: Port 35729 is already in use by another process.
  13. 如何计算列表项的出现?
  14. StringBufferStringBuilder 源码详解
  15. python ppt表格样式展示
  16. Python暴力破解rar、zip压缩文件密码
  17. 人脸识别门禁系统设计(一)
  18. 数据库原理与应用学习笔记(一)
  19. uniapp 微信小程序 腾讯位置服务路线规划插件的使用
  20. MySql数据库操作详解

热门文章

  1. python前段管理3
  2. spring boot和spring cloud的区别_Spring聊聊application和bootstrap
  3. c语言for循环语句java,C语言三种类型的循环语句
  4. Deep Learning for Computer Vision with MATLAB and cuDNN
  5. 数据结构与算法(1)——数组与链表
  6. Learning hard C#学习笔记 C#简介
  7. 重磅开源人工智能大型场景草图数据集图像检索草图着色编辑和字幕
  8. InnoDB 存储引擎体系架构
  9. Java程序员从笨鸟到菜鸟之(十)枚举,泛型详解
  10. java设计模式6--适配器模式(Adapter )