基於閾值分解的多級中值濾波

基於閾值分解的多級中值濾波
基於閾值分解的多級中值濾波的結構如下所示:
這裏寫圖片描述
首先對整個圖像統計,得到均值m,和標準差δ,並進行閾值的分解,閾值分解函數Ti()爲:
這裏寫圖片描述
從圖1中,噪灰度圖像首先在(m-kδ)和(m+kδ),兩個閾值上分解爲2個二值圖像。k爲參數,適當選擇k可以使這2個二值圖像反映大部分脈衝噪聲所處位置的信息。2幅二值圖像經過中值濾波後再分別於濾波之前的二值圖像作“異或Xor”運算,其目的是得到已被濾除的脈衝噪聲位置。然後再對2幅圖做“或or”運算,就可以得到總體脈衝噪聲位置分佈矩陣。最後在噪聲位置處濾波,這樣可以在去除噪聲的同時儘可能地保留細節。
代碼如下:

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;

void YZmedian(Mat& I, Mat& Iout, int n=3, double k=1.6)
{
    cvtColor(I,I,COLOR_BGR2GRAY);//灰度圖轉換
    Mat temp_m,temp_std;   //定義均值方差矩陣
    meanStdDev(I,temp_m,temp_std);//求均值方差矩陣
    double Im_m=temp_m.at<double>(0,0);//均值
    double Im_std=temp_std.at<double>(0,0);//方差


    double t1=Im_m-k*Im_std;//閾值1
    double t2=Im_m+k*Im_std;//閾值2

    Mat I1=I.clone();
    Mat I2=I.clone();

    int width=I.cols;
    int height=I.rows;
    for (int i = 0; i < height; i++)
    {     
        uchar* data1 =I1.ptr<uchar>(i);
        uchar* data2=I2.ptr<uchar>(i);
        for (int j = 0; j < width; j++)
        {
            if (data1[j]>=t1)
            {
                data1[j]=1;
            }
            else
            {
                data1[j]=0;
            }
            if (data2[j]>=t2)
            {
                data2[j]=1;
            }
            else
            {
                data2[j]=0;
            }
        }
    }

    Mat I11,I22;
    medianBlur(I1,I11,n);//中值濾波
    medianBlur(I2,I22,n);//中值濾波

    Mat I111,I222;
    bitwise_xor(I1,I11,I111);
    bitwise_xor(I2,I22,I222);

    Mat I3;
    bitwise_or(I111,I222,I3);

    /*擴展邊界方便濾波*/
    Mat I4(Size(I3.rows+(n-1),I3.cols+(n-1)),CV_8U,Scalar(0));
    Mat I5(Size(I3.rows+(n-1),I3.cols+(n-1)),CV_8U,Scalar(0));
    I.copyTo(I4(Range((n-1)/2,I4.rows-(n-1)/2),Range((n-1)/2,I4.cols-(n-1)/2)));
    I3.copyTo(I5(Range((n-1)/2,I4.rows-(n-1)/2),Range((n-1)/2,I4.cols-(n-1)/2)));

    //在噪聲處濾波
    for (int i = 0; i < I4.rows; i++)
    {
        uchar* data1=I4.ptr<uchar>(i);
        uchar* data2=I5.ptr<uchar>(i);
        for (int j = 0; j < I4.cols; j++)
        {
            if(data2[j]==1)
            {
                Mat roi=I4(Range(i-(n-1)/2,i+(n-1)/2),Range(j-(n-1)/2,j+(n-1)/2));
                resize(roi,roi,Size(1,n*n));
                Mat index;
                sortIdx(roi,index,SORT_EVERY_COLUMN+SORT_ASCENDING);
                int x=index.at<int>((n*n-1)/2);
                data1[j]=roi.at<uchar>(x);
            }
        }
    }
    Iout=I4(Range((n-1)/2,I4.rows-(n-1)/2),Range((n-1)/2,I4.cols-(n-1)/2)).clone(); 
}




int main()
{  

    Mat I=imread("Nimg.png");//讀取原始圖片
    Mat Iout;
    Mat Imdian;
    medianBlur(I,Imdian,7);
    YZmedian(I,Iout,7,1.6);
    imshow("原始圖像",I);
    imshow("基於閾值分解的多級中值濾波後的圖像",Iout);
imshow("傳統中值濾波",Imdian);

    waitKey(0);
    return 0;
}

結果如下圖所示:
這裏寫圖片描述

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