關於中值濾波演算法,以及C語言實現
關於中值濾波演算法,以及C語言實現
2017年04月06日 11:45:58
閱讀數:1464
1、什麼是中值濾波?
中值濾波是對一個滑動視窗內的諸畫素灰度值排序,用其中值代替視窗中心象素的原來灰度值,它是一種非線性的影象平滑法,它對脈衝干擾級椒鹽噪聲的抑制效果好,在抑制隨機噪聲的同時能有效保護邊緣少受模糊。
中值濾波可以過濾尖峰脈衝。目的在於我們對於濾波後的資料更感興趣。濾波後的資料保留的原影象的變化趨勢,同時去除了尖峰脈衝對分析造成的影響。
-
以一維訊號的中值濾波舉例。對灰度序列80、120、90、200、100、110、70,如果按大小順序排列,其結果為70、80、90、10O、110、120、200,其中間位置上的灰度值為10O,則該灰度序列的中值即為100。一維訊號中值濾波實際上就是用中值代替規定位置(一般指原始訊號序列中心位置)的訊號值。對前面所舉的序列而言,中值濾波的結果是用中值100替代序列80、120、90、200、100、110、70中的訊號序列中心位置值200,得到的濾波序列就是80、120、90、100、100、110、70。如果在此序列中200是一個噪聲訊號,則用此方法即可去除這個噪聲點。
-
二維中值濾波演算法是:對於一幅影象的象素矩陣,取以目標象素為中心的一個子矩陣視窗,這個視窗可以是3*3 ,5*5 等根據需要選取,對視窗內的象素灰度排序,取中間一個值作為目標象素的新灰度值。視窗示例如ooooxoooo上面x為目標象素,和周圍o組成3*3矩陣Array,然後對這9個元素的灰度進行排序,以排序後的中間元素Array[4]為x的新灰度值,如此就完成物件素x的中值濾波,再迭代對其他需要的象素進行濾波即可。
影象處理中,中值濾波的實現方法
1:通過從影象中的某個取樣視窗取出奇數個數據進行排序
2:用排序後的中值取代要處理的資料即可
中值濾波的
把濾波區間的資料從小到大進行排序,然後取中值,(如果是奇數個數據,那麼中值就只有一個了,如果偶數個數據,中值有兩個,可以對兩個資料再求平均)
下面是一個C語言實現中值濾波的函式:
-
unsigned char GetMedianNum(int * bArray, int iFilterLen)
-
{
-
int i,j;// 迴圈變數
-
unsigned char bTemp;
-
// 用冒泡法對陣列進行排序
-
for (j = 0; j < iFilterLen - 1; j ++)
-
{
-
for (i = 0; i < iFilterLen - j - 1; i ++)
-
{
-
if (bArray[i] > bArray[i + 1])
-
{
-
// 互換
-
bTemp = bArray[i];
-
bArray[i] = bArray[i + 1];
-
bArray[i + 1] = bTemp;
-
}
-
}
-
}
-
// 計算中值
-
if ((iFilterLen & 1) > 0)
-
{
-
// 陣列有奇數個元素,返回中間一個元素
-
bTemp = bArray[(iFilterLen + 1) / 2];
-
}
-
else
-
{
-
// 陣列有偶數個元素,返回中間兩個元素平均值
-
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
-
}
-
return bTemp;
-
}
注:bArray 是一個整形指標,我們傳入的一般是一個數組,用來儲存待排序的資料
iFilterLen 是濾波器的長度
用在影象處理中時,由於畫素的取值範圍是0~255,剛好是unsigned char 的範圍,所以函式的返回值是unsigned char,如果我們要處理的數是float型,或其他型別,返回值也可以更改~~返回值是bTemp,也即是我們想得到的中值
下面是一個完整的C語言程式
-
/*************************************************************************
-
* 函式名稱:
-
* MedianFilter()
-
* 引數:
-
* int iFilterH - 濾波器的高度
-
* int iFilterW - 濾波器的寬度
-
* int iFilterMX - 濾波器的中心元素X座標
-
* int iFilterMY - 濾波器的中心元素Y座標
-
* 說明:
-
* 該函式對DIB影象進行中值濾波。
-
************************************************************************/
-
#define iFilterW 1
-
#define iFilterH 1
-
#define iFilterMX 1
-
#define iFilterMY 1
-
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
-
unsigned char GetMedianNum(int * bArray, int iFilterLen);
-
void MedianFilter(unsigned char *pImg1,unsigned char *pImg,int nWidth,int nHeight)
-
{
-
unsigned char *lpSrc; // 指向源影象的指標
-
unsigned char *lpDst; // 指向要複製區域的指標
-
int aValue[iFilterH*iFilterW]; // 指向濾波器陣列的指標
-
int i,j,k,l; // 迴圈變數
-
int lLineBytes; // 影象每行的位元組數
-
lLineBytes = WIDTHBYTES(nWidth * 8);
-
for ( i=0;i<nWidth;i++,pImg++ )
-
(*pImg)=0;
-
// 開始中值濾波
-
// 行(除去邊緣幾行)
-
for(i = iFilterMY; i < nHeight - iFilterH + iFilterMY + 1; i++)
-
{
-
// 列(除去邊緣幾列)
-
for(j = iFilterMX; j < nWidth - iFilterW + iFilterMX + 1; j++)
-
{
-
// 指向新DIB第i行,第j個象素的指標
-
lpDst = pImg + lLineBytes * (nHeight - 1 - i) + j;
-
// 讀取濾波器陣列
-
for (k = 0; k < iFilterH; k++)
-
{
-
for (l = 0; l < iFilterW; l++)
-
{
-
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l個象素的指標
-
lpSrc = pImg1 + lLineBytes * (nHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
-
// 儲存象素值
-
aValue[k * iFilterW + l] = *lpSrc;
-
}
-
}
-
// 獲取中值
-
* lpDst = GetMedianNum(aValue, iFilterH * iFilterW);
-
}
-
}
-
}
-
unsigned char GetMedianNum(int * bArray, int iFilterLen)
-
{
-
int i,j; // 迴圈變數
-
unsigned char bTemp;
-
// 用冒泡法對陣列進行排序
-
for (j = 0; j < iFilterLen - 1; j ++)
-
{
-
for (i = 0; i < iFilterLen - j - 1; i ++)
-
{
-
if (bArray[i] > bArray[i + 1])
-
{
-
// 互換
-
bTemp = bArray[i];
-
bArray[i] = bArray[i + 1];
-
bArray[i + 1] = bTemp;
-
}
-
}
-
}
-
// 計算中值
-
if ((iFilterLen & 1) > 0)
-
{
-
// 陣列有奇數個元素,返回中間一個元素
-
bTemp = bArray[(iFilterLen + 1) / 2];
-
}
-
else
-
{
-
// 陣列有偶數個元素,返回中間兩個元素平均值
-
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
-
}
-
return bTemp;
-
}
文章標籤: C 語言