中值濾波的快速算法

我想學過圖像處理的人沒有人會不知道中值濾波的,最早的時候我是在岡薩雷斯的圖像處理課本[1]中學到的,後來在看Sonka的書[2]的時候又看到了中值濾波的介紹,下面我試着結合課本所學和網上的資料自己整理一篇中值濾波的介紹。

Jeremy Lin

中值濾波器是一種統計排序濾波器,由Tukey於1971年在文獻[3]中提出。所謂的統計排序濾波器是一種非線性的空間濾波器,它的響應基於圖像濾波器包圍的圖像區域中像素的排序,然後用統計排序結果決定的值代替中心像素的值。除了中值濾波器外,最大值濾波器和最小值濾波器也是統計排序濾波器。在介紹中值濾波器之前,我們先來了解一下中值的概念,中值是一個將概率分佈的高半部分與低半部分分開的值。對一個隨機變量x而言,x<M的概率爲0.5。對於有限實數集,其排序後中間的數值即爲它的中值。這樣,我們就可以很清楚的知道,中值濾波就是將鄰域內像素(包括中心像素值)灰度值的中值代替中心像素的值。


在圖像處理中,中值濾波的使用非常的普遍,這是因爲對於一定類型的隨機噪聲,它提供了一種優秀的去噪能力,相比於小尺寸的線性平滑濾波器的模糊程度要低很多。而且它對處理脈衝噪聲(椒鹽噪聲)非常有效。那它爲什麼能夠去噪呢?我們知道,因爲噪聲的出現,使某像素點比周圍的像素亮(暗)許多,若與周圍的像素值一起排序,噪聲點則位於序列的前端或末端,序列中值通常沒有受到噪聲污染,因此,可以用中值取代原像素值來達到出去噪聲的效果。


下面我們看一個直觀的例子:

f = imread('C:/a.jpg');
f_gray = rgb2gray(f);
subplot(1,3,1);
imshow(f_gray);
title('原圖');
fn = imnoise(f_gray, 'salt & pepper', 0.2);
subplot(1,3,2);
imshow(fn);
title('椒鹽噪聲');
fm = medfilt2(fn, 'symmetric');
subplot(1,3,3);
imshow(fm);
title('中值濾波');



從上圖可以看出,中值濾波後的效果還是相當不錯的。


接下來,我們着重看看如何實現中值濾波。

Pseudo Code:

   allocate outputPixelValue[image width][image height]
   edgex := (window width / 2) rounded down
   edgey := (window height / 2) rounded down
   for x from edgex to image width - edgex
       for y from edgey to image height - edgey
           allocate colorArray[window width][window height]
           for fx from 0 to window width
               for fy from 0 to window height
                   colorArray[fx][fy] := inputPixelValue[x + fx - edgex][y + fy - edgey]
           sort all entries in colorArray[][]
           outputPixelValue[x][y] := colorArray[window width / 2][window height / 2]

C++ Code:

bool median_Filter (unsigned char* input, unsigned char* output, int height, int weight)
{
	if (input == NULL)
	{
		return false;
	}
	memset (output, 0, sizeof(unsigned char)*height*weight);
	for (int i = 1; i < height-1; ++i)
	{
		for (int j = 1; j < weight-1; ++j)
		{
			int k = 0;
			unsigned char filter_Region[9];
			for (int ii = i-1; ii < i+2; ++ii)
			{
				for (int jj = j-1; jj < j+2; ++jj)
				{
					filter_Region[k++] = input[ii+width + jj];
				}
			}
			for (int m = 0; m < 5; ++m)
			{
				int min = m;
				for (int n = m+1; n < 9; ++n)
				{
					if (filter_Region[n] < filter_Region[min])
					{
						min = n;
					}
				}
				unsigned char tmp = filter_Region[m];
				filter_Region[m] = filter_Region[min];
				filter_Region[min] = tmp;
			}
			output[i*width + j] = filter_Region[4];
		}
	}
	return true;
}

從上面的程序可以發現,在每個像素位置上都要對一個矩形內部的所有像素進行排序,這樣的開銷會變得很大。因此下面介紹一種更爲有效的方法[4],我們注意到當窗口沿着行移動一列時,窗口內容的變化只是丟掉最左邊的列取代爲一個新的右側列,對於m行n列的中值窗口,mn-2*m個像素沒有變化,並不需要重新排序。算法如下:





本文地址:http://blog.csdn.net/linj_m/article/details/35780163

更多資源 請關注 博客 LinJM-機器視覺 微博:林建民-機器視覺

Refs:

[1] Gonzalez R C. 阮秋琦, 等譯[M]. 數字圖像處理. 第 2 版. 北京: 電子工業出版社, 2007.

[2] 松卡, 赫拉瓦奇, 博伊爾. 圖像處理, 分析與機器視覺[M]. 人民郵電出版社, 2002.

[3] J.W. Tukey, Exploratory Data Analysis ( preliminary ed.). Reading MA: Addison-Wesley, 1971.

[4] Thomas S. Huang , A fast Two-dimensional median filtering algorithm, 1979.下載地址:LinJM

[5] http://siee.cumt.edu.cn/Signalgroup/Imaging/kc/525.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章