中值滤波和均值滤波的C++实现
最后更新于:2022-04-01 23:03:08
#中值滤波
中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值.中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为3*3,5*5区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
**以3*3的滤波窗口为例:**
中值滤波就是在3*3中的像素中寻找中值。 来看这样一个描述图(不然无图无真相)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d65263e69db.png)
这把可以清晰地看到, 这里有6,2,0,3,97,4,19,3,10这些像素, 然后中间的这些像素值就被这些像素的中位数也就是中值取代了。为了满足和前面一篇文章的格式相对应, 我们马上进入下一个单元, 来看看在平滑和降噪方面的功效!
原图1 中值滤波之后
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652636f5fa.png)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d6526417c71.png)
噪声图(5%) 中值滤波后:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652642fb70.png)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652644f0bc.png)
很明显中值滤波不仅使得图像变得平滑(也可以理解为图像变得模糊了),但是其对去除了椒盐噪声特别有效,因为中值滤波就是专门针对去除孤立点噪声孕育为生的。从这里中值的逻辑来看, 我们做中值操作的时候, 那么白色(接近255的像素点)和黑色(接近0的像素)因为在窗口排序时是最大最小值, 除非周围的颜色都是黑色或者白色,不然一般都会被剔除掉,所以,一般来说这个中值滤波是去除椒盐噪声的非常理想的选择。
最后还是贴一段我运行的代码:
~~~
void medianFilter(BYTE* pcorrPic, BYTE* psmoothPic, int width, int height)
{
memcpy(psmoothPic, pcorrPic, width*height*sizeof(BYTE));
for (int j = 1; j < height - 1; j++)//排除邻边
{
for (int i = 1; i < width - 1; i++)
{
int k = 0;
BYTE window[9];
for (int jj = j - 1; jj < j + 2; ++jj)
for (int ii = i - 1; ii < i + 2; ++ii)
window[k++] = pcorrPic[jj * width + ii];
// 元素排序 (一半即可)
for (int m = 0; m < 5; ++m)
{
int min = m;
for (int n = m + 1; n < 9; ++n)
if (window[n] < window[min])
min = n;
// 找到最小值应该放置的位置
BYTE temp = window[m];
window[m] = window[min];
window[min] = temp;
}
psmoothPic[j*width + i] = window[4];
}
}
}
~~~
#均值滤波
“**把每个像素都用周围的9个像素来做均值操作** ”, 比如说这里有一个例子:
![sample](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d6526476bae.png)
非常明显的, 这个3*3区域像素的颜色值分别是5,3,6,2,1,9,8,4,7那么中间的1这个像素的过滤后的值就是这些值的平均值, 也就是前面的计算方法: (5+3+6+2+1+9+8+4+7)/9=5
一目了然。那么这个均值滤波器有什么用处呢?
主要还是平滑图像的用处, 有的图像的锐度很高,用这样的均值算法,可以把锐度降低。使得图像看上去更加自然,下面就有几幅图我们可以看出一些端倪:
原图: 原图均值滤波处理之后:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652636f5fa.png)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652649c013.png)
这里还是可以明显的感觉到不同的, 没有好坏之分,就是第二幅图片看上去更为平滑。 继续我们的问题, 那这里均值平滑是否具有去除噪声的功能呢? 我们搞来了椒盐噪声(就是随机的白点,黑点)来试试手:
噪声图(5%椒盐噪声): 均值滤波平滑处理之后:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d652642fb70.png)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-02_56d65264bc95d.png)
首先这里的噪声还是比较小的, 只有5%,从均值的效果来看的话, 我可以说几乎没有用,其实直观的想也可以判断, 因为这里的处理并没有剔除这些噪声点, 而只是微弱地降低了噪声,所以效果可以想见的。。
好吧, 最后的时候还是贴上一段处理的C++均值滤波算法代码:
~~~
void meanFilter (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{
memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) ); //复制数据
for (int j=1;j
';