图像噪声源于现实世界中数字信号总会受到各种各样的干扰,最终接受的图像和源于的数字信号之间总
是存在一定的差异,对于图像噪声,使用均值滤波和中值滤波来消除图像噪声的做法已经是很常见的图
像消噪手段。
一:图像加噪原理
1. 椒盐噪声(salt and pepper noise)
椒盐噪声是一种因为信号脉冲强度引起的噪声,信噪比(signal noiserate)是衡量图像噪声的一个数字指标。
给一副数字图像加上椒盐噪声的处理顺序应该如下:
指定信噪比 snr 其取值范围在[0, 1]之间
计算总像素数目 sp, 得到要加噪的像素数目 np = sp * (1-snr)
随机获取要加噪的每个像素位置p(i, j)
指定像素值为255或者0。
重复c, d两个步骤完成所有像素的np个像素
输出加噪以后的图像
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. 将伪随机数带入g(d)得到高斯随机数
d. 根据输入像素计算出输出像素
e. 重新将像素值防缩在[0 ~ 255]之间
f. 循环所有像素
g. 输出图像
二:关键程序解析
1. 椒盐噪声
根据信噪比,获取要加入椒盐噪声的像素数目
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;
}
2. 高斯噪声
根据标准方差,和伪随机数的范围,首先计算出一个伪随机数d ,根据d得到高斯分布的随机数值,整个代码如下:
float d = (float)math.random()*random_scope - random_scope/2;
float sigma2 = sigma*sigma*2;
float pi2 = (float)math.pi * 2;
float sigmapi2 = (float)math.sqrt(pi2*sigma);
float result = (float)math.exp(-d/sigma2)/sigmapi2;
伪随机数的范围为[-127~ 127]之间。
获取高斯噪声的像素代码如下:
tr = (int)((float)tr + getgaussianvalue() + this.means);
tg = (int)((float)tg + getgaussianvalue() + this.means);
tb = (int)((float)tb + getgaussianvalue() + this.means);
mean是的值为0.
三:程序效果如下
加入白色椒盐噪声的图片
加入高斯噪声的图片
椒盐噪声的代码如下:
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;
}
高斯噪声的代码如下:
private bufferedimage gaussiannoise(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];
int[][][] temppixels = new int[height][width][4];
int[] outpixels = new int[width*height];
getrgb( src, 0, 0, width, height, inpixels );
int index = 0;
float inmax = 0;
float outmax = 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(inmax < tr) {
inmax = tr;
}
if(inmax < tg) {
inmax = tg;
if(inmax < tb) {
inmax = tb;
tr = (int)((float)tr + getgaussianvalue() + this.means);
tg = (int)((float)tg + getgaussianvalue() + this.means);
tb = (int)((float)tb + getgaussianvalue() + this.means);
if(outmax < tr) {
outmax = tr;
if(outmax < tg) {
outmax = tg;
if(outmax < tb) {
outmax = tb;
temppixels[row][col][0] = ta;
temppixels[row][col][1] = tr;
temppixels[row][col][2] = tg;
temppixels[row][col][3] = tb;
}
}
// normalization
index = 0;
float rate = inmax/outmax;
ta = temppixels[row][col][0];
tr = temppixels[row][col][1];
tg = temppixels[row][col][2];
tb = temppixels[row][col][3];
tr = (int)((float)tr * rate);
tg = (int)((float)tg * rate);
tb = (int)((float)tb * rate);
outpixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
setrgb( dst, 0, 0, width, height, outpixels );
return dst;
}