基于阈值分解的多级中值滤波-附代码
基于阈值分解的多级中值滤波的结构如下所示:
首先对整个图像统计,得到均值m,和标准差δ,并进行阈值的分解,阈值分解函数Ti()为:
从图1中,噪灰度图像首先在(m-kδ)和(m+kδ),两个阈值上分解为2个二值图像。k为参数,适当选择k可以使这2个二值图像反映大部分脉冲噪声所处位置的信息。2幅二值图像经过中值滤波后再分别于滤波之前的二值图像作“异或Xor”运算,其目的是得到已被滤除的脉冲噪声位置。然后再对2幅图做“或or”运算,就可以得到总体脉冲噪声位置分布矩阵。最后在噪声位置处滤波,这样可以在去除噪声的同时尽可能地保留细节。
代码如下:
#include
#include
#include
#include
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(0,0);//均值
double Im_std=temp_std.at(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(i);
uchar* data2=I2.ptr(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(i);
uchar* data2=I5.ptr(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((n*n-1)/2);
data1[j]=roi.at(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;
}