數字圖像處理之快速中值濾波算法

快速中值濾波算法

  中值濾波算法

      在圖像處理中,在進行如邊緣檢測這樣的進一步處理以前,一般須要首先進行必定程度的降噪。中值濾波是一種非線性數字濾波器技術,常常用於去除圖像或者其它信號中的噪聲。這個設計思想就是檢查輸入信號中的採樣並判斷它是否表明了信號,使用奇數個採樣組成的觀察窗實現這項功能。觀察窗口中的數值進行排序,位於觀察窗中間的中值做爲輸出。而後,丟棄最先的值,取得新的採樣,重複上面的計算過程。中值濾波是圖像處理中的一個經常使用步驟,它對於斑點噪聲和椒鹽噪聲來講尤爲有用。保存邊緣的特性使它在不但願出現邊緣模糊的場合也頗有用。html

 

      爲了演示中值濾波器的工做過程,咱們給下面的數組加上觀察窗 3 ,重複邊界的數值:ios

      x = [2 80 6 3]c++

      y[1] = Median[2 2 80] = 2
      y[2] = Median[2 80 6] = Median[2 6 80] = 6
      y[3] = Median[80 6 3] = Median[3 6 80] = 6
      y[4] = Median[6 3 3] = Median[3 3 6] = 3算法

      因而
      y = [2 6 6 3]數組

      其中 y 是 x 的中值濾波輸出。ide

       普通中值濾波算法僞代碼:

      Input: image X of size m*n, kernel radius r.ui

      output: image Y as X.spa

      for i = r to m - r do 設計

        for j = r to n - r do3d

          initialize list A[]

          for a = i-r to i+r

            for b = j-r to j+r

              add X(a, b) to  A[]

            end 

          end

          sort A[] then Y(i ,j) = A[A.size/2]

        end

      end

      處理前:                                                                  

                     

       處理後:         

      

     可是,上述算法在像素處理處的複雜度爲O(r2).

 

  OpenCV實現代碼:

#include "cv.h"
#include "highgui.h"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
        Mat src = imread("beauty.jpg");
        Mat dst;

        //參數是按順序寫的

        //高斯濾波
        //src:輸入圖像
        //dst:輸出圖像
        //Size(5,5)模板大小,爲奇數
        //x方向方差
        //Y方向方差
        GaussianBlur(src,dst,Size(5,5),0,0);
        imwrite("gauss.jpg",dst);
        
        //中值濾波
        //src:輸入圖像
        //dst::輸出圖像
        //模板寬度,爲奇數
        medianBlur(src,dst,3);
        imwrite("med.jpg",dst);
        
        //均值濾波
        //src:輸入圖像
        //dst:輸出圖像
        //模板大小
        //Point(-1,-1):被平滑點位置,爲負值取核中心
        blur(src,dst,Size(3,3),Point(-1,-1));
        imwrite("mean.jpg",dst);

        //雙邊濾波
        //src:輸入圖像
        //dst:輸入圖像
        //濾波模板半徑
        //顏色空間標準差
        //座標空間標準差
        bilateralFilter(src,dst,5,10.0,2.0);//這裏濾波沒什麼效果,不明白
        imwrite("bil.jpg",dst);

        waitKey();

        return 0;
}
View Code

 

  快速中值濾波算法:

     O(r)複雜度的Huang算法:<A Fast Two-Dimensional Median Filtering Algorithm>

 

                     

    這個代碼的核心在於維護一個kernel直方圖,能夠實現快速的讀取和刪除掃描區域的像素值。

int StopAmount = (2 * Radius + 1) * (2*Radius +1) * Percentile;
int Sum = 0;
for (int I = 0; I <= 255; I++)
{
    Sum += HistBlue(I);
    if (Sum >= StopAmount)      // 知足中止條件
    {
        Value = I;              // 獲得中值
        break; 
    }
}

 

    在MFC中實現的huang算法:

/******************************************************************
* 功能: 彩色圖像的快速中值濾波平滑處理
* 參數: image0爲原圖形,image1平滑結果,
*        w、h爲圖象的寬和高
*       size爲進行平滑的鄰域邊長
******************************************************************/
void FastSmoothMedianCl(BYTE* image0, BYTE* image1, unsigned int w, unsigned int h, unsigned int size)
{
    //將圖像轉化爲矩陣形式
    BYTE** imageBuf0 = CreatImage(image0, w, h);
    BYTE** imageBuf1 = CreatImage(image1, w, h);
    //設定模板
    int x,y,c;
    int a;
    //int scale;
    int ** templt;
    //初始化 x = size/2 爲中心的點的直方圖,

    
    //根據鄰域大小設定模板
    templt = new int*[5];
    for(c=0; c<3; c++)
    {
        templt[c] = new int [256];
    }

    for(y=size/2; y<h-size/2; y++)
    {
        for(c=0; c<3; c++)
        {
            for (int i= 0; i< 256; i ++){
                templt[c][i] = 0;
            }
            for(int i = y-size/2; i < y+size/2; i++){
                for (int j = 0; j < size; j++){
                    int k = imageBuf0[i][j*4+c];
                    templt[c][k] ++;
                }
            }
        }
        for(x=size/2+1; x<w-size/2; x++)
        {
            for(c=0; c<3; c++)
            {
                //取採樣窗口中像素灰度的中值
                a=FastMedianValueCl(imageBuf0,w,h,templt,size,x,y,c);
                //a/= scale;
                //過限處理
                a = a>255?255:a;    
                a = a<0?0:a;
                imageBuf1[y][x*4+c]=a;
            }
        }
    }
    
    //清理內存
    for(int i = 0; i < 3; i ++){
        delete templt[i];
    }
    free(imageBuf0);
    free(imageBuf1);
}

/**************************************************
* 功能: 使用直方圖對彩色圖鄰域獲取中值
* 參數: imageBuf爲目標圖像 w、h爲圖像大小
*       templt爲模板 tw爲鄰域大小 
*        x,y爲當前採樣窗口中心像素的座標
*       cn爲顏色份量編號 0爲藍色 1爲綠色 2爲紅色
**************************************************/
int FastMedianValueCl(BYTE** imageBuf0, int w, int h, int**templt, int tw, int x, int y, int cn)
{
    int i,j,k;                   
    int px,py, mid;
    int count = 0;                 //用來保存採樣窗口的像素數量
    int count_temp = 0;
    k=0;

    //從採樣窗口中取得像素灰度
    for(i=0; i<tw; i++)
    {
            py=y-tw/2+i;
            px=x+tw/2+1;
            //若是該像素位於採樣窗口
            //保存像素灰度
            k = imageBuf0[py][px*4+cn];
            templt[cn][k]++;

            px=x-tw/2;
            //保存像素灰度
            k = imageBuf0[py][px*4+cn];
            templt[cn][k]--;
    }
    for(int a = 0; a < 256; a++){
        mid = a;
        count_temp += templt[cn][a];
        if(count_temp > (tw*tw)/2) break;
    }

    return mid;
}
View Code

    與普通算法的比較:

    O(1)複雜度的CTMF算法:<Median Filter in Constant Time.pdf>

  首先,對於每一列圖像,咱們都爲其維護一個直方圖(對於8位圖像,該直方圖有256個元素),在整個的處理過程當中,這些直方圖數據都必須獲得維護。每列直方圖累積了2r+1個垂直方向上相鄰像素的信息,初始的時候,這2r+1個像素是分別以第一行的每一個像素爲中心的。核的直方圖經過累積2r+1個相鄰的列直方圖數據獲取。其實,咱們所作的就是將核直方圖分解成他對應的列直方圖的集合,在整個濾波的過程當中,這些直方圖數據在兩個步驟內用恆定的時間保持最新。

  考慮從某個像素向右移動一個像素的狀況。對於當前行,核最右側的列直方圖首先須要更新,而此時該列的列直方圖中的數據仍是以上一行對應位置那個像素爲中心計算的。所以須要減去最上一個像素對應的直方圖而後加上其下面一像素的直方圖信息。這樣作的效果就是將列直方圖數據下降一行。這一步很明顯是個0(1)操做,只有一次加法和一次減法,而於半徑r無關。

      第二步更新核直方圖,其是2r+1個列直方圖之和。這是經過減去最左側的列直方圖數據,而後再加上第一步所處理的那一列的列直方圖數據得到的。這一步也是個O(1)操做,如圖2所示。如前所述,加法、減法以及計算直方圖的中值的耗時都是一些依賴於圖像位深的計算,而於濾波半徑無關。

                     

    這個算法較以前的Huang算法的差異在於,充分利用了以前的數據,這有點相似於動態規劃,也是用空間換取時間的策略。

 

 

 參考博客:http://www.cnblogs.com/Imageshop/archive/2013/04/26/3045672.html

相關文章
相關標籤/搜索