图像加噪和图像滤波

 

1.     椒盐噪声(Salt And Pepper Noise

椒盐噪声是一种因为信号脉冲强度引起的噪声,信噪比(Signal NoiseRate)是衡量图像噪声的一个数字指标。

给一副数字图像加上椒盐噪声的处理顺序应该如下:

  1. 指定信噪比 SNR 其取值范围在[0, 1]之间
  2. 计算总像素数目 SP得到要加噪的像素数目 NP = SP * (1-SNR)
  3. 随机获取要加噪的每个像素位置Pi, j
  4. 指定像素值为255或者0
  5. 重复c, d两个步骤完成所有像素的NP个像素
  6. 输出加噪以后的图像

  

int noise_num=(int)height*width*SNR/2;
for(int i=0; i<noise_num; i++)
    {
        int row = (int)(rand()%height);
        int col = (int)(rand()%width);
        for(int j=0;j<nChannels;j++)
        {
        des[row * width* nChannels + col* nChannels+j]= 255;
        }
 
    }
        for(int i=0; i<noise_num; i++)
    {
        int row = (int)(rand()%height);
        int col = (int)(rand()%width);
        for(int j=0;j<nChannels;j++)
        {
        des[row * width* nChannels + col* nChannels+j]=0;
        }
     }

  

2.     高斯噪声(Gaussian Noise

高斯噪声的密度取决于公式G(x, sigma) 其中X是代表平均值,sigma代表的标准方差,每个输入像素 Pin,

一个正常的高斯采样分布公式G(d), 得到输出像素Pout.

       Pout = Pin + XMeans + sigma *G(d)

其中d为一个线性的随机数,G(d)是随机数的高斯分布随机值。

给一副数字图像加上高斯噪声的处理顺序如下:

a.      输入参数sigam X mean

b.      以系统时间为种子产生一个伪随机数

c.      将伪随机数带入Gd)得到高斯随机数

d.      根据输入像素计算出输出像素

e.      重新将像素值防缩在[0 ~ 255]之间

f.       循环所有像素

g.      输出图像

采用了由MarsagliaBray1964年提出的常用成熟的生成高斯分布随机数序列的方法

double gaussrand(int M,int D)
{
    static double V1, V2, S;
    static int phase = 0;
    double X;
    if ( phase == 0 ) {
        do {
            double U1 = (double)rand() / RAND_MAX;
            double U2 = (double)rand() / RAND_MAX;
            
            V1 = 2 * U1 - 1;
            V2 = 2 * U2 - 1;
            S = V1 * V1 + V2 * V2;
        } while(S >= 1 || S == 0)
        X = V1 * sqrt(-2 * log(S) / S);
    } else
        X = V2 * sqrt(-2 * log(S) / S); 
    phase = 1 - phase;
    X=X*D+M;
    return(X);
}

  

3.均匀噪声

采用了经典的均匀噪声序列生成:

double randomUniform(double dMinValue,double dMaxValue)
{
 
    double pRandomValue = (double)(rand()/(double)RAND_MAX);
    pRandomValue = pRandomValue*(dMaxValue-dMinValue)+dMinValue;
    return pRandomValue;
}

  

二、滤波器的原理与实现

1.修正的阿尔法均值滤波器

假设在领域clip_image002内去掉gst)最低灰度值的d/2和最高灰度值的d/2。令clip_image004代表剩下的mn-d个像素。由剩余这些像素的平均值形成的滤波器成为修正的阿尔法均值滤波器:

clip_image006

下面是核心的算法:

//Alpha trimmed mean filter
void Alphatrimmedmeanfilter(unsigned char* des, const unsigned char* src, int width, int height, int nChannels)
{
         // TODO: Add your command handler code here
                            //processing
                            int len=9;         //定义模板大小为3*3
                            double* or=new double[len];     //将模板中强度记录成序列待排序
                            int d=4;     //定义d值
                            //将uint8型转换为double型
                            //filtering
                                     for(int x=2;x<width-2;x++)
                                               for(int y=2;y<height-2;y++)
                                                        for(int n=0;n<nChannels;n++)
                                                   {
                                                        or[0]=src[(y-1)*width*nChannels+(x-1)*nChannels + n];
                                                        or[1]=src[(y-1)*width*nChannels+x*nChannels + n];
                                                        or[2]=src[(y-1)*width*nChannels+(x+1)*nChannels + n];
                                                        or[3]=src[y*width*nChannels+(x-1)*nChannels + n];
                                                        or[4]=src[y*width*nChannels+x*nChannels + n];
                                                        or[5]=src[y*width*nChannels+(x+1)*nChannels + n];
                                                        or[6]=src[(y+1)*width*nChannels+(x-1)*nChannels + n];
                                                        or[7]=src[(y+1)*width*nChannels+x*nChannels + n];
                                                        or[8]=src[(y+1)*width*nChannels+(x+1)*nChannels + n];
                                              
                                                   orderN(or,9);           //从小到大排序
                                                   double sum=0;         //记录剩余强度之和
                                                   for(int k=d/2;k<9-d/2;k++)
                                                   {
                                                           sum=sum+or[k];
                                                   }
                                                   sum=sum/(9-d);
                                                   des[y*width*nChannels+x*nChannels + n]=int(sum);
                                                 }         
}

  

2.自适应中值滤波:

自适应中值滤波器的滤波方式和传统的中值滤波器一样,都使用一个矩形区域的窗口Sxy ,不同的是在滤波过程中,自适应滤波器会根据一定的设定条件改变,即增加滤窗的大小,同时当判断滤窗中心的像素是噪声时,该值用中值代替,否则不改变其当前像素值,这样用滤波器的输出来替代像素(x,y) (即目前滤窗中心的坐标的值。我们做如下定义:

Zmin是在Sxy滤窗内灰度的最小值;

Zmax是在Sxy滤窗内灰度的最大值;

Zmed是在Sxy滤窗内灰度的中值;

Zxy是坐标(x,y 处的灰度值;

         Smax指定Sxy所允许的最大值。 

自适应中值滤波算法由两个部分组成,称为第一层(Level A) 和第二层(Level B)  主要算法如下:

Level A : A1 = Zmed - Zmin A2 = Zmed - Zmax

如果A1> 0 并且A2<0 ,转到level B ,否则增加滤窗Sxy的尺寸。 如果滤窗SxySmax ,则重复执行Level A ,否则把Zxy作为输出值。

Level B : B1 = Zxy - Zmin B2 = Zxy - Zmax

如果B1>0 并且B2<0 , Zxy作为输出值, 否则把Zmed作为输出值。

算法如下:

void Adaptivemedianfilter(unsigned char* des, const unsigned char* src, int width, int height, int nChannels)
{
         // TODO: Add your command handler code here
                            int s=5;     //定义最大矩形框大小
                            int k=0;
                            k=(s-1)/2;
                            //filtering
                            double medtemp=0;
                            double maxtemp=0;
                            double mintemp=0;
                            double pxytemp=0;             //定义滤波过程中的临时变量
                            for(int i=2;i<width-2;i++)
                                     for(int j=2;j<height-2;j++)            //逐点扫描
                                         for(int n=0;n<nChannels;n++)
                                               {
                                        int len=3;
                                        while(len<=s)
                                        {
                                                 double* or=new double[len*len];         //动态分配一维序列存放
                                                            int len2=0;
                                                            len2=(len-1)/2;
                                                            for(int x=0;x<len;x++)            //将矩形框中的数据读入or进行排序
                                                                     for(int y=0;y<len;y++)
                                                                     {
                                                                               or[x*len+y]=src[(i-len2+x)*nChannels+(j-len2+y)*nChannels*width+n];
                                                                     }
                                                            orderN(or,len*len);
                                                            medtemp=or[(len*len-1)/2];
                                                            maxtemp=or[len*len-1];
                                                            mintemp=or[0];
                                                            pxytemp=src[i*nChannels+j*nChannels*width+n];
                                                            if((maxtemp>medtemp)&(mintemp<medtemp))
                                                            {
                                                                 if((maxtemp>pxytemp)&(mintemp<pxytemp))
                                                                 {
                                                                           des[i*nChannels+j*nChannels*width+n]=int(pxytemp);
                                                                 }
                                                                 else
                                                                 {
                                                                           des[i*nChannels+j*nChannels*width+n]=int(medtemp);
                                                                 }
                                                                 break;
                                                        }
                                                        else
                                                        {
                                                                 len=len+2;
                                                        }
                                                        delete []or;
                                               }
                                              if(len>s)
                                               {
                                                        des[i*nChannels+j*nChannels*width+n]=int(medtemp);
                                               }
                                     }
}

  

  

三、结果分析:

1.15%的均匀噪声和10%的椒盐噪声及对其进行修正的阿尔法滤波(d=4mn=9)后的结果:

clip_image008clip_image010

通过实验,发现d的取值对结果影响比较大,在d=4是取得比较好的结果,但可以看出依然有一些噪声点。

2.25%的椒盐噪声及对其自适应中值滤波后的结果:

clip_image012clip_image014

可以看到自适应中值滤波对于椒盐噪声可以说具有非常漂亮的滤波效果,基本上看不出和原图像的区别。但是细心观察可以发现处理后的图像景物的边缘相对原图像比较模糊。

3.20%的均值为0,方差900的高斯噪声及其维纳滤波后的效果:

clip_image016clip_image018

 

posted @ 2016-03-05 18:56  HUSTLX  阅读(4246)  评论(0编辑  收藏  举报