廖雪峰历时3个月打磨出价值1980的数据分析教程,终终终于免费啦!

文章目录
  1. 1. 前言
  2. 2. 椒盐噪声(Salt And Pepper Noise)
  3. 3. 高斯噪声(Gaussian Noise)
  4. 4. 泊松噪声
  5. 5. 程序效果
  6. 6. 全部代码

前言

  • 图像处理的实验,用matlab捣鼓了一会最后还是觉得Java用的比较顺手,所以使用Java实现的给图像加噪声,分别给图像添加椒盐噪声、高斯噪声、泊松分布噪声。

    椒盐噪声(Salt And Pepper Noise)

  • 椒盐噪声是一种因为信号脉冲强度引起的噪声,信噪比(Signal NoiseRate)是衡量图像噪声的一个数字指标。
  • 给一副数字图像加上椒盐噪声的处理顺序应该如下:
    1. 指定信噪比 SNR 其取值范围在[0, 1]之间
    • 计算总像素数目 SP, 得到要加噪的像素数目 NP = SP * (1-SNR)
    • 随机获取要加噪的每个像素位置P(i, j)
    • 指定像素值为255或者0。
    • 重复3, 4两个步骤完成所有像素的NP个像素
    • 输出加噪以后的图像

代码如下:

/*
 * 椒盐噪声
 */
private BufferedImage addSaltAndPepperNoise(BufferedImage src, BufferedImage dst) {  
    int width = src.getWidth();  
       int height = src.getHeight();  

       if ( dst == null )  
           dst = createCompatibleDestImage( src, null );  

       int[] inPixels = new int[width*height];  
       getRGB( src, 0, 0, width, height, inPixels );  

       int index = 0;  
       int size = (int)(inPixels.length * (1-SNR));  

       for(int i=0; i<size; i++) {  
        int row = (int)(Math.random() * (double)height);  
        int col = (int)(Math.random() * (double)width);  
        index = row * width + col;  
        inPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 255;  
       }  

       setRGB( dst, 0, 0, width, height, inPixels );  
       return dst;  
}

高斯噪声(Gaussian Noise)

  • 高斯噪声的密度取决于公式G(x, sigma) 其中X是代表平均值,sigma代表的标准方差,每个输入像素 Pin,
    一个正常的高斯采样分布公式G(d), 得到输出像素Pout.
    Pout = Pin + XMeans + sigma *G(d)
    
  • 其中d为一个线性的随机数,G(d)是随机数的高斯分布随机值。
  • 给一副数字图像加上高斯噪声的处理顺序如下:

    1. 输入参数sigam 和 X mean
    • 系统时间为种子产生一个伪随机数
    • 将伪随机数带入G(d)得到高斯随机数
    • 根据输入像素计算出输出像素
    • 重新将像素值防缩在[0 ~ 255]之间
    • 循环所有像素
    • 输出图像
  • 代码如下:

    /*
     * 添加高斯噪声
     */
    private int addGNoise(int tr, Random random) {  
        int v, ran;  
        boolean inRange = false;  
        do {  
            ran = (int)Math.round(random.nextGaussian()*_mNoiseFactor);  //均值为0.0,标准差为1.0的高斯分布
            v = tr + ran;  
            // check whether it is valid single channel value  
            inRange = (v>=0 && v<=255);   
            if (inRange) tr = v;  
        } while (!inRange);  
        return tr;   
    }  
    
    public static int clamp(int p) {  
        return p > 255 ? 255 : (p < 0 ? 0 : p);  
    }  
    

泊松噪声

  • 泊松噪声,就是噪声分布符合泊松分布模型。泊松分布(Poisson Di)的公式如下:




  • 关于泊松分布的详细解释看这里:http://zh.wikipedia.org/wiki/泊松分佈.

  • 代码如下:

     /*
     * 泊松噪声
     */
    private int addPNoise(int pixel, Random random) {  
        // init:  
        double L = Math.exp(-_mNoiseFactor * MEAN_FACTOR);  
        int k = 0;  
        double p = 1;  
        do {  
            k++;  
            // Generate uniform random number u in [0,1] and let p ← p × u.  
            p *= random.nextDouble();  
        } while (p >= L);  
        double retValue = Math.max((pixel + (k - 1) / MEAN_FACTOR - _mNoiseFactor), 0);  
        return (int)retValue;  
    }  
    

    程序效果

  • 原图

  • 高斯噪声

  • 椒盐噪声

全部代码

package lab3;
import java.awt.image.BufferedImage;  
import java.util.Random;  
public class NoiseAdditionFilter extends AbstractBufferedImageOp {  
    public final static double MEAN_FACTOR = 2.0;  
    public final static int POISSON_NOISE_TYPE = 2;  //泊松噪声
    public final static int GAUSSION_NOISE_TYPE = 1;  //高斯噪声
    public final static int Salt_NOISE_TYPE = 3;  //椒盐噪声
    private double _mNoiseFactor = 100;   //高斯分布数值大小
    private int _mNoiseType = 2;    //选择噪声
    private static final double SNR = 0.5;   //椒盐噪声信噪比
    public NoiseAdditionFilter() {  
        System.out.println("Adding Poisson/Gaussion Noise");  
    }  
    public void setNoise(double power) {  
        this._mNoiseFactor = power;  
    }  
    public void setNoiseType(int type) {  
        this._mNoiseType = type;  
    }  
    @Override  
    public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
        int width = src.getWidth();  
        int height = src.getHeight();  
        Random random = new Random();  
        if ( dest == null )  
            dest = createCompatibleDestImage( src, null );  
        int[] inPixels = new int[width*height];  
        int[] outPixels = new int[width*height];  
        getRGB( src, 0, 0, width, height, inPixels );  
        int index = 0;  
        for(int row=0; row<height; row++) {  
            int ta = 0, tr = 0, tg = 0, tb = 0;  
            for(int col=0; col<width; col++) {  
                index = row * width + col;  
                ta = (inPixels[index] >> 24) & 0xff;  
                tr = (inPixels[index] >> 16) & 0xff;  
                tg = (inPixels[index] >> 8) & 0xff;  
                tb = inPixels[index] & 0xff;  
                if(_mNoiseType == Salt_NOISE_TYPE) {
                    return this.addSaltAndPepperNoise(src,dest);
                }
                if(_mNoiseType == POISSON_NOISE_TYPE) {  
                    tr = clamp(addPNoise(tr, random));  
                    tg = clamp(addPNoise(tg, random));  
                    tb = clamp(addPNoise(tb, random));  
                } else if(_mNoiseType == GAUSSION_NOISE_TYPE) {  
                    tr = clamp(addGNoise(tr, random));  
                    tg = clamp(addGNoise(tg, random));  
                    tb = clamp(addGNoise(tb, random));  
                }  
                outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
            }  
        }  
  System.out.println("fd");
        setRGB( dest, 0, 0, width, height, outPixels );  
        return dest;  
    }  
    /*
     * 添加高斯噪声
     */
    private int addGNoise(int tr, Random random) {  
        int v, ran;  
        boolean inRange = false;  
        do {  
            ran = (int)Math.round(random.nextGaussian()*_mNoiseFactor);  //均值为0.0,标准差为1.0的高斯分布
            v = tr + ran;  
            // check whether it is valid single channel value  
            inRange = (v>=0 && v<=255);   
            if (inRange) tr = v;  
        } while (!inRange);  
        return tr;   
    }  

    public static int clamp(int p) {  
        return p > 255 ? 255 : (p < 0 ? 0 : p);  
    }  
    /*
     * 泊松噪声
     */
    private int addPNoise(int pixel, Random random) {  
        // init:  
        double L = Math.exp(-_mNoiseFactor * MEAN_FACTOR);  
        int k = 0;  
        double p = 1;  
        do {  
            k++;  
            // Generate uniform random number u in [0,1] and let p ← p × u.  
            p *= random.nextDouble();  
        } while (p >= L);  
        double retValue = Math.max((pixel + (k - 1) / MEAN_FACTOR - _mNoiseFactor), 0);  
        return (int)retValue;  
    }  
    /*
     * 椒盐噪声
     */
    private BufferedImage addSaltAndPepperNoise(BufferedImage src, BufferedImage dst) {  
        int width = src.getWidth();  
           int height = src.getHeight();  
           if ( dst == null )  
               dst = createCompatibleDestImage( src, null );  
           int[] inPixels = new int[width*height];  
           getRGB( src, 0, 0, width, height, inPixels );  

           int index = 0;  
           int size = (int)(inPixels.length * (1-SNR));  

           for(int i=0; i<size; i++) {  
            int row = (int)(Math.random() * (double)height);  
            int col = (int)(Math.random() * (double)width);  
            index = row * width + col;  
            inPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 255;  
           }  
           setRGB( dst, 0, 0, width, height, inPixels );  
           return dst;  
    }
}  

科学上网(翻墙)教程!

更多精彩内容,请扫描二维码关注公众号:轮子工厂,公众号内回复:

1.回复【图书】:获取15本新手自学编程,零基础入门经典学习教材;
2.回复【我要造轮子】:获取100多本计算机类经典书籍;
3.回复【开发工具】:获取几大主流编程语言的开发工具~
4.回复【内推】:可帮你内推到大厂工作。
文章目录
  1. 1. 前言
  2. 2. 椒盐噪声(Salt And Pepper Noise)
  3. 3. 高斯噪声(Gaussian Noise)
  4. 4. 泊松噪声
  5. 5. 程序效果
  6. 6. 全部代码