图像中的噪声就是图像中的杂点或者干扰成分,噪声主要产生于图像的获取和传输过程中。噪声一般分为分为加性噪声和乘性噪声。
其中f(x,y)表示图像,g(x,y)表示没有噪声的图像部分,q表示噪声。这两种噪声可以通过取对数和指数相互转换:
常见的几种噪声有,高斯噪声、瑞利噪声、指数噪声和椒盐噪声。除椒盐噪声以外其他三种均属于加性噪声。椒盐噪声既不属于加性噪声也不属于乘性噪声。
噪声是有噪声分量灰度值的统计特性来描述的,它们可以被认为是由概率密度函数(PDF)表示的随机变量,下面是几种噪声的概率密度函数。
高斯随机变量z的概率密度函数为:
μ表示z的期望值,σ表示z的方差。
瑞利噪声的概率密度函数为:
它的均值和方差分别为a+√(πb)/4和b(4-π)/4。
指数分布噪声的概率密度函数为:
它的均值和方差分别为1/a和1/a2,其中a>0。
椒盐噪声又称双击脉冲噪声,它类似于随机分布在图像上的胡椒(黑色)和盐粒(白色)。它的概率密度函数为:
对于一个8位深度图像,a=0,b=255.
下面仅将添加高斯噪声和椒盐噪声的代码贴出:
-
-
-
-
-
-
-
-
- public static bool AddNoise(Bitmap srcBmp, NoiseType noiseType, double[] para, out Bitmap dstBmp) {
- dstBmp = null;
- if (srcBmp == null) { return false; }
- dstBmp = new Bitmap(srcBmp);
- BitmapData bmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- Random r1 = new Random(unchecked((int)DateTime.Now.Ticks));
- Random r2 = new Random(~unchecked((int)DateTime.Now.Ticks));
- double temp, tempR, tempG, tempB, v1, v2;
-
- unsafe {
- byte* ptr = (byte*)bmpData.Scan0;
- switch (noiseType) {
- case NoiseType.GAUSSIAN:
- for (int i = 0; i < bmpData.Height; i++) {
- for (int j = 0; j < bmpData.Width; j++) {
- do {
- v1 = r1.NextDouble();
- } while (v1 <= 0.00000000001);
- v2 = r2.NextDouble();
-
- temp = Math.Sqrt(-2 * Math.Log(v1)) * Math.Cos(2 * Math.PI * v2) * para[1] + para[0];
- tempB = temp + ptr[i * bmpData.Stride + j * 3];
- tempG = temp + ptr[i * bmpData.Stride + j * 3 + 1];
- tempR = temp + ptr[i * bmpData.Stride + j * 3 + 2];
- tempB = tempB > 255 ? 255 : tempB; tempB = tempB < 0 ? 0 : tempB;
- tempG = tempG > 255 ? 255 : tempG; tempG = tempG < 0 ? 0 : tempG;
- tempR = tempR > 255 ? 255 : tempR; tempR = tempR < 0 ? 0 : tempR;
- ptr[i * bmpData.Stride + j * 3] = (byte)tempB;
- ptr[i * bmpData.Stride + j * 3 + 1] = (byte)tempG;
- ptr[i * bmpData.Stride + j * 3 + 2] = (byte)tempR;
- }
- }
- break;
- case NoiseType.SALTPEPPER:
- for (int i = 0; i < bmpData.Height; i++) {
- for (int j = 0; j < bmpData.Width; j++) {
- v1 = r1.NextDouble();
- if (v1 <= para[0]) {
- temp = -500;
- }
- else {
- if (v1 >= 1 - para[1]) {
- temp = 500;
- }
- else {
- temp = 0;
- }
- }
- tempB = temp + ptr[i * bmpData.Stride + j * 3];
- tempG = temp + ptr[i * bmpData.Stride + j * 3 + 1];
- tempR = temp + ptr[i * bmpData.Stride + j * 3 + 2];
- tempB = tempB > 255 ? 255 : tempB; tempB = tempB < 0 ? 0 : tempB;
- tempG = tempG > 255 ? 255 : tempG; tempG = tempG < 0 ? 0 : tempG;
- tempR = tempR > 255 ? 255 : tempR; tempR = tempR < 0 ? 0 : tempR;
- ptr[i * bmpData.Stride + j * 3] = (byte)tempB;
- ptr[i * bmpData.Stride + j * 3 + 1] = (byte)tempG;
- ptr[i * bmpData.Stride + j * 3 + 2] = (byte)tempR;
- }
- }
- break;
- default:
- break;
- }
- }
- dstBmp.UnlockBits(bmpData);
- return true;
- }
效果图: