在CSDN的第一篇博客
摘要
本文主要完成对 Thomas S Huang, George J Yang, and Gregory J Yang. A Fast Two-Dimensional Median Filtering Algorithm[J]. IEEE Transactions on Acoustics Speech and Signal Processing, 1979, 27(1): 13-18. 论文中算法的实现。论文中算法应用于灰度图像,这里我也把它扩展到RGB图像,其基本原理是一致的,对于RGB图像需要对三个通道分别进行快速中值滤波。
算法流程及伪代码
算法流程
快速二维中值滤波算法主要有以下几个步骤:
(1)先建立第一个要处理的像素点的滤波器窗口灰度等级直方图,并找到这个窗口内所有像素点灰度值的中值,并计算窗口内小于中值的灰度值数量,存入ltmdn。
(2)将窗口中心移动到下一个像素点,同时更新灰度直方图为当前窗口的,并更新当前窗口的ltmdn。
(3)根据当前的ltmdn与窗口像素点总数/2的关系,向上/向下寻找当前窗口的灰度中值。
(4)若当前像素点不是某一行的最后一个,则转到步骤2;若当前像素点为某一行的最后一个,且不是要处理的最后一行,则将窗口中心移动到下一行的第一列的像素点,再转到步骤1;否则,流程结束。
注:处理彩色图像时,对于每一个像素点要建立RGB三个通道的滤波器窗口灰度直方图,并对每一个通道单独求中值以及更新直方图。
该算法忽略了对图像边界的滤波处理,边界值不进行中值滤波,直接保留原始的灰度值。
伪代码
1. //Richard Chen
2. Begin
3. hist[255]={
0}//存储256级灰度
4. mdn //存储灰度中值
5. ltmdn //记录当前滤波器窗口中,灰度值小于mdn的像素点个数
6. window_x_size //滤波器窗口列数
7. window_y_size //滤波器窗口行数
8. th=window_x_size*window_y_size/2 //用于帮助寻找中值
9. left.column[window_y_size]//存储上一个窗口最左侧一列的数据
10. right.column[window_y_size]//存储当前窗口最右侧一列的数据
11.
12. for (i=window_y_size/2 +1;i<picture_y_size-window_y_size/2;i++)
13. {
14. 先对每一行的第一个像素点构建灰度直方图,并找到当前窗口的中值mdn和对应的ltmdn
15. for(j=window_x_size/2 +2 ;j<picture_x_size-window_x_size/2;j++)
16. {
17. 更新直方图,对于上一个窗口最左侧一列的数据,在直方图中删去,
18. 对于当前窗口最右侧一列的数据,加进直方图中,同时如果有灰度值小于mdn,ltmdn也要相应改变
19. for(k=0;k<window_y_size;k++)
20. {
21. hist[left.column[k]]--;
22. if(left.column[k]<mdn)ltmdn--;
23. hst[right.column[k]]++;
24. if(right.column[k]<ltmdn)ltmdn++;
25. }
26. 更新完直方图后,根据现在的ltmdn来快速寻找新的中值mdn
27. if(ltmdn>th)
28. {
29. while(ltmdn>th)
30. {
31. mdn--;
32. ltmd-=hist[mdn];
33. }
34. }
35. else
36. {
37. while(ltmdn+hist[mdn]<=th)
38. {
39. ltmdn+=hist[mdn];
40. mdn++;
41. }
42. }
43.
44. 将找到的中值mdn存入新图中对应的位置
45. 注:这里滤波结果应该存入新图中,不能存入原图,否则会对后续滤波产生影响。
46. }
47. }
48. end
程序代码
算法使用C++进行实现,并用其对三张图片进行了处理。三张图片分别为原始图片,在原始图片上添加了5%椒盐噪声的图片,在原始图片上添加了高斯噪声的图片,高斯噪声的均值为0,方差为1,为了增强噪声效果,我对每一个像素点的高斯噪声幅值增加到了原始幅值的10倍。
程序使用opencv读取和保存图片,中值滤波函数为自己写的(作业要求嘛…)
/***********************************************
*
* DIP homework: A Fast Two-Dimensional Median Filtering Algorithm
* Author: Richard Chen
* Date: 2019.12
* Institute: NJUST
* 功能:实现灰度图和彩色图的二维快速中值滤波算法,并于传统中值滤波进行了比较
*
************************************************/
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
clock_t startTime, endTime;
#define window_x_size 3 //定义窗口的大小
#define window_y_size 3
#define window_size window_x_size *window_y_size
#define th window_size / 2 //用于寻找中值
struct hist_3d
{
int Blue[256] = {
0 };
int Green[256] = {
0 };
int Red[256] = {
0 };
};
Mat Add_salt_noise(const Mat src, int num)
{
Mat dst = src.clone();
int n = 0, i = 0, j = 0, flag = 0;
for (n = 0; n < num; n++)
{
//随机取行列
i = rand() % dst.rows;
j = rand() % dst.cols;
flag = rand() % 2; //用于决定加椒还是加盐噪声 flag=0或1
if (flag)
{
if (dst.channels() == 1) //图像通道判定 判别灰度图还是RGB图
{
dst.at<uchar>(i, j) = 255; //盐噪声
}
else
{
dst.at<Vec3b>(i, j)[0] = 255;
dst.at<Vec3b>(i, j)[1] = 255;
dst.at<Vec3b>(i, j)[2] = 255;
}
}
else
{
if (dst.channels() == 1)
{
dst.at<uchar>(i, j) = 0; //椒噪声
}
else
{
dst.at<Vec3b>(i, j)[0] = 0;
dst.at<Vec3b>(i, j)[1] = 0;
dst.at<Vec3b>(i, j)[2] = 0;
}
}
}
return dst;
}
//生成高斯噪声
double generateGaussianNoise(double mu, double sigma)