中值濾波算法以某像素的領域圖像區域中的像素值的排序爲基礎,將像素領域內灰度的中值代替該像素的值[1];html
如:以3*3的領域爲例求中值濾波中像素5的值git
圖1github
1)int pixel[9]中存儲像素1,像素2...像素9的值;算法
2)對數組pixel[9]進行排序操做;windows
3)像素5的值即爲數組pixel[9]的中值pixel[4]。數組
中值濾波對處理椒鹽噪聲很是有效。網絡
項目工程:https://github.com/ranjiewwen/Everyday_Practice/tree/master/MedianFilter/MedianFilter/MedianFilterspa
//中值濾波:本算法採用3*3的領域範圍 void MyImage::MedianFilterOper() { //0. 準備:獲取圖片的寬,高和像素信息, int const num = 3 * 3; unsigned char pixel[num] = { 0 }; //保存領域的像素值 int width = m_bmpInfo.biWidth; int height = m_bmpInfo.biHeight; int widthbyte = (width * m_bmpInfo.biBitCount / 8 + 3) / 4 * 4; //保證爲4的倍數 //相對於中心點,3*3領域中的點須要偏移的位置 int delta[3 * 3][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 0 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, {1, 1} }; //1. 中值濾波,沒有考慮邊緣 for (int i = 1; i < height-1; ++i) { for (int j = 1; j < widthbyte-1; ++j) { //1.1 提取領域值 for (int k = 0; k < num; ++k) { pixel[k] = m_imagedata[(i + delta[k][0])*widthbyte + j + delta[k][1]]; } //1.2 排序 qsort(pixel, num, sizeof(unsigned char), compa); //1.3 獲取該中心點的值 m_imagedata[i*widthbyte + j] = pixel[num / 2]; } } }
中值濾波是基於排序統計理論的一種能有效抑制噪聲的非線性信號平滑處理技術,它將每一像素點的灰度值設置爲該點某鄰域窗口內的全部像素點灰度值的中值。code
中值濾波的基本原理是把數字圖像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,從而消除孤立的噪聲點。方法是用某種結構的二維滑動模板,將板內像素按照像素值的大小進行排序,生成單調上升(或降低)的爲二維數據序列。二維中值濾波輸出爲g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分別爲原始圖像和處理後圖像。W爲二維模板,一般爲3*3,5*5區域,也能夠是不一樣的的形狀,如線狀,圓形,十字形,圓環形等。htm
中值濾波數學實現:對一個數字信號序列xj(-∞<j<∞)進行濾波處理時,首先要定義一個長度爲奇數的L長窗口,L=2N+1,N爲正整數。設在某一個時刻,窗口內的信號樣本爲x(i-N),…,x(i),…,x(i+N),其中x(i)爲位於窗口中心的信號樣本值。對這L個信號樣本值按從小到大的順序排列後,其中值,在i處的樣值,便定義爲中值濾波的輸出值。
在實際應用中,隨着所選用窗口長度的增長,濾波的計算量將會迅速增長。所以,尋求中值濾波的快速算法,是中值濾波理論的一個重要研究內容。中值濾波的快速算法,通常採用下述三種方式:①直方圖數據修正法;②樣本值二進制表示邏輯判斷法;③數字和模擬的選擇網絡法。
對中值濾波的理論研究,還集中於統計特性分析和根序列的描述方面。當一個信號序列經一特定窗口長度的中值濾波反覆處理後,它會收斂於某一個再也不變化的序列,這個序列稱爲中值濾波的根序列。根序列是描述中值濾波特性的一個重要概念。經過對根序列結構的研究,能夠肯定原信號序列中,哪些成分能夠經中值濾波後保留下來,哪些成分將被抑制。這對肯定中值濾波器的窗口長度,提供了重要依據。用VLSI實現的中值濾波器芯片,可供實時處理中應用。
// zhongzhilvbo.cpp : 定義控制檯應用程序的入口點。 // #include <stdio.h> #include <math.h> #include <memory.h> #include <conio.h> #include <stdlib.h> #include <windows.h> #include "stdafx.h" //原圖象的寬度和高度 #define width 352 #define higth 288 int lvbo(unsigned char D[9]) //冒泡排序 { unsigned int temp; int i,j; for(i=0;i<9;i++) { for(j=0;j<9-i;j++) { if(D[i]>D[j+1]) { temp=D[i]; D[i]=D[j+1]; D[j+1]=temp; } } } return D[4]; } void main() { FILE *fp,*newfp; int i,j; if(!(fp=fopen("fmh1.bmp","rb"))) { printf("Open file %s error!\n","k.bmp"); return ; } if(!(newfp=fopen("fmout.bmp","wb"))) { printf("Open file %s error!\n","result.bmp"); return ; } unsigned char buffer[54+1024];//定義原圖像頭緩衝區 fread(buffer,1,54+1024,fp);//讀取文件頭54個字節 unsigned long length=width*higth;//圖像的總象素個數 unsigned char readData[higth][width]; //用於存儲原圖數據的數組 unsigned char writeData[higth][width]; //用於存儲原圖數據的數組 fread(&readData[0][0], sizeof(unsigned char),length, fp);//從原圖讀入數據 for(i=0;i<higth;i++) { for(j=0;j<width;j++) { writeData[i][j]=readData[i][j]; } } unsigned char D[9]; //定義選取框 for(i=1;i<higth-1;i++) { for(j=1;j<width-1;j++) { D[0]=readData[i-1][j+1]; D[1]=readData[i][j+1]; D[2]=readData[i+1][j+1]; D[3]=readData[i-1][j]; D[4]=readData[i][j]; D[5]=readData[i+1][j]; D[6]=readData[i-1][j-1]; D[7]=readData[i][j-1]; D[8]=readData[i+1][j-1]; writeData[i][j]=lvbo(D); } } fwrite(buffer,sizeof(unsigned char),54+1024,newfp); fwrite(writeData,sizeof(unsigned char),length,newfp); fclose(newfp); fclose(fp); return ; }
參考:http://www.cnblogs.com/tanfy/p/median_filter.html
http://www.cnblogs.com/qiqibaby/p/5281743.html