1。邻域平均法
噪声点像素的灰度与其临近像素的灰度显著不同,根据噪声点这一特性,可以使用邻域平均法。
Bitmap desc = new Bitmap(source.Width, source.Height);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
*(descptr++) = (byte)((*(sourceptr - (step + 3)) + *(sourceptr - step) + *(sourceptr - (step - 3)) +
*(sourceptr - 3) + *(sourceptr) + *(sourceptr + 3) +
*(sourceptr + (step - 3)) + *(sourceptr + step) + *(sourceptr + (step + 3))) / 9);
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
*(descptr++) = (byte)((*(sourceptr - (step + 3)) + *(sourceptr - step) + *(sourceptr - (step - 3)) +
*(sourceptr - 3) + *(sourceptr) + *(sourceptr + 3) +
*(sourceptr + (step - 3)) + *(sourceptr + step) + *(sourceptr + (step + 3))) / 9);
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
2。加权平均法
邻域平均处理方法是以图像模糊为代价减小噪声。有时为了突出源图像中的点(i, j)本身的重要性,对于同一尺寸的模板,不同位置的系数采用不同的数值就可以采用加权平均法实现。
Bitmap desc = new Bitmap(source.Width, source.Height);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
*(descptr++) = (byte)((*(sourceptr - (step + 3)) + *(sourceptr - step) * 2 + *(sourceptr - (step - 3))+
*(sourceptr - 3) * 2 + *(sourceptr) * 4 + *(sourceptr + 3) * 2 +
*(sourceptr + (step - 3)) + *(sourceptr + step) * 2 + *(sourceptr + (step + 3))) / 16);
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
*(descptr++) = (byte)((*(sourceptr - (step + 3)) + *(sourceptr - step) * 2 + *(sourceptr - (step - 3))+
*(sourceptr - 3) * 2 + *(sourceptr) * 4 + *(sourceptr + 3) * 2 +
*(sourceptr + (step - 3)) + *(sourceptr + step) * 2 + *(sourceptr + (step + 3))) / 16);
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
3。选择式掩膜平滑
邻域平均法和加权平均法在消除噪声的同时,都不可避免地带来平均化的缺憾,致使尖锐变化的边缘或线条变得模糊。考虑图像中目标物体和背景一般都具有不同的统计特性,即不同的均值和方差,为保留一定的边缘信息,可采用选择式掩膜平滑滤波,这样可以得到较好的图像细节。这种方法以尽量不模糊边缘轮廓为目的。

Bitmap desc = new Bitmap(source.Width, source.Height);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0; //B,G,R
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
sourceptr += step * 2;
descptr += step * 2;
byte[] pixel = new byte[9];
float[,] mean = new float[9,3];
float[,] var = new float[9,3];
int n, m;
float min;
for (int x = 2; x < source.Height - 2; x++)
{
sourceptr += 6;
descptr += 6;
for (int y = 2; y < source.Width - 2; y++)
{
for (int color = 0; color < 3; color++)
{
pixel[0] = *(sourceptr - (step + 3));
pixel[1] = *(sourceptr - step);
pixel[2] = *(sourceptr - (step - 3));
pixel[3] = *(sourceptr - 3);
pixel[4] = *(sourceptr);
pixel[5] = *(sourceptr + 3);
pixel[6] = *(sourceptr + (step - 3));
pixel[7] = *(sourceptr + step);
pixel[8] = *(sourceptr + (step + 3));
mean[0, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6] + pixel[7] + pixel[8]) / 9;
var[0, color] = 0;
for (n = 0; n < 9; n++)
var[0, color] += pixel[n] * pixel[n] - mean[0, color] * mean[0, color];
pixel[0] = *(sourceptr - (step + 6));
pixel[1] = *(sourceptr - (step + 3));
pixel[2] = *(sourceptr - 6);
pixel[3] = *(sourceptr - 3);
pixel[4] = *(sourceptr);
pixel[5] = *(sourceptr + (step - 6));
pixel[6] = *(sourceptr + (step - 3));
mean[1, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[1, color] = 0;
for (n = 0; n < 7; n++)
var[1, color] += pixel[n] * pixel[n] - mean[1, color] * mean[1, color];
pixel[0] = *(sourceptr - (step + step + 3));
pixel[1] = *(sourceptr - (step + step));
pixel[2] = *(sourceptr - (step + step - 3));
pixel[3] = *(sourceptr - (step + 3));
pixel[4] = *(sourceptr - step);
pixel[5] = *(sourceptr - (step - 3));
pixel[6] = *(sourceptr);
mean[2, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[2, color] = 0;
for (n = 0; n < 7; n++)
var[2, color] += pixel[n] * pixel[n] - mean[2, color] * mean[2, color];
pixel[0] = *(sourceptr - (step - 3));
pixel[1] = *(sourceptr - (step - 6));
pixel[2] = *(sourceptr);
pixel[3] = *(sourceptr + 3);
pixel[4] = *(sourceptr + 6);
pixel[5] = *(sourceptr + (step + 3));
pixel[6] = *(sourceptr + (step + 6));
mean[3, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[3, color] = 0;
for (n = 0; n < 7; n++)
var[3, color] += pixel[n] * pixel[n] - mean[3, color] * mean[3, color];
pixel[0] = *(sourceptr);
pixel[1] = *(sourceptr + (step - 3));
pixel[2] = *(sourceptr + step);
pixel[3] = *(sourceptr + (step + 3));
pixel[4] = *(sourceptr + (step + step - 3));
pixel[5] = *(sourceptr + step + step);
pixel[6] = *(sourceptr + (step + step + 3));
mean[4, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[4, color] = 0;
for (n = 0; n < 7; n++)
var[4, color] += pixel[n] * pixel[n] - mean[4, color] * mean[4, color];
pixel[0] = *(sourceptr - (step + step + 6));
pixel[1] = *(sourceptr - (step + step + 3));
pixel[2] = *(sourceptr - (step + 6));
pixel[3] = *(sourceptr - (step + 3));
pixel[4] = *(sourceptr - step);
pixel[5] = *(sourceptr - 3);
pixel[6] = *(sourceptr);
mean[5, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[5, color] = 0;
for (n = 0; n < 7; n++)
var[5, color] += pixel[n] * pixel[n] - mean[5, color] * mean[5, color];
pixel[0] = *(sourceptr - (step + step - 3));
pixel[1] = *(sourceptr - (step + step - 6));
pixel[2] = *(sourceptr - step);
pixel[3] = *(sourceptr - (step - 3));
pixel[4] = *(sourceptr - (step - 6));
pixel[5] = *(sourceptr);
pixel[6] = *(sourceptr + 3);
mean[6, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[6, color] = 0;
for (n = 0; n < 7; n++)
var[6, color] += pixel[n] * pixel[n] - mean[6, color] * mean[6, color];
pixel[0] = *(sourceptr);
pixel[1] = *(sourceptr + 3);
pixel[2] = *(sourceptr + step);
pixel[3] = *(sourceptr + (step + 3));
pixel[4] = *(sourceptr + (step + 6));
pixel[5] = *(sourceptr + (step + step + 3));
pixel[6] = *(sourceptr + (step + step + 6));
mean[7, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[7, color] = 0;
for (n = 0; n < 7; n++)
var[7, color] += pixel[n] * pixel[n] - mean[7, color] * mean[7, color];
pixel[0] = *(sourceptr - 3);
pixel[1] = *(sourceptr);
pixel[2] = *(sourceptr + (step - 6));
pixel[3] = *(sourceptr + (step - 3));
pixel[4] = *(sourceptr + step);
pixel[5] = *(sourceptr + (step + step - 6));
pixel[6] = *(sourceptr + (step + step - 3));
mean[8, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[8, color] = 0;
for (n = 0; n < 7; n++)
var[8, color] += pixel[n] * pixel[n] - mean[8, color] * mean[8, color];
descptr++;
sourceptr++;
}
min = var[0, 0] + var[0, 1] + var[0, 2];
m = 0;
for (n = 1; n < 9; n++)
{
if (min > var[n, 0] + var[n, 1] + var[n, 2])
{
min = var[n, 0] + var[n, 1] + var[n, 2];
m = n;
}
}
*(descptr - 3) = (byte)(mean[m, 0]);
*(descptr - 2) = (byte)(mean[m, 1]);
*(descptr - 1) = (byte)(mean[m, 2]);
}
sourceptr += sourcedata.Stride - source.Width * 3 + 6;
descptr += descdata.Stride - desc.Width * 3 + 6;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0; //B,G,R
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
sourceptr += step * 2;
descptr += step * 2;
byte[] pixel = new byte[9];
float[,] mean = new float[9,3];
float[,] var = new float[9,3];
int n, m;
float min;
for (int x = 2; x < source.Height - 2; x++)
{
sourceptr += 6;
descptr += 6;
for (int y = 2; y < source.Width - 2; y++)
{
for (int color = 0; color < 3; color++)
{
pixel[0] = *(sourceptr - (step + 3));
pixel[1] = *(sourceptr - step);
pixel[2] = *(sourceptr - (step - 3));
pixel[3] = *(sourceptr - 3);
pixel[4] = *(sourceptr);
pixel[5] = *(sourceptr + 3);
pixel[6] = *(sourceptr + (step - 3));
pixel[7] = *(sourceptr + step);
pixel[8] = *(sourceptr + (step + 3));
mean[0, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6] + pixel[7] + pixel[8]) / 9;
var[0, color] = 0;
for (n = 0; n < 9; n++)
var[0, color] += pixel[n] * pixel[n] - mean[0, color] * mean[0, color];
pixel[0] = *(sourceptr - (step + 6));
pixel[1] = *(sourceptr - (step + 3));
pixel[2] = *(sourceptr - 6);
pixel[3] = *(sourceptr - 3);
pixel[4] = *(sourceptr);
pixel[5] = *(sourceptr + (step - 6));
pixel[6] = *(sourceptr + (step - 3));
mean[1, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[1, color] = 0;
for (n = 0; n < 7; n++)
var[1, color] += pixel[n] * pixel[n] - mean[1, color] * mean[1, color];
pixel[0] = *(sourceptr - (step + step + 3));
pixel[1] = *(sourceptr - (step + step));
pixel[2] = *(sourceptr - (step + step - 3));
pixel[3] = *(sourceptr - (step + 3));
pixel[4] = *(sourceptr - step);
pixel[5] = *(sourceptr - (step - 3));
pixel[6] = *(sourceptr);
mean[2, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[2, color] = 0;
for (n = 0; n < 7; n++)
var[2, color] += pixel[n] * pixel[n] - mean[2, color] * mean[2, color];
pixel[0] = *(sourceptr - (step - 3));
pixel[1] = *(sourceptr - (step - 6));
pixel[2] = *(sourceptr);
pixel[3] = *(sourceptr + 3);
pixel[4] = *(sourceptr + 6);
pixel[5] = *(sourceptr + (step + 3));
pixel[6] = *(sourceptr + (step + 6));
mean[3, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[3, color] = 0;
for (n = 0; n < 7; n++)
var[3, color] += pixel[n] * pixel[n] - mean[3, color] * mean[3, color];
pixel[0] = *(sourceptr);
pixel[1] = *(sourceptr + (step - 3));
pixel[2] = *(sourceptr + step);
pixel[3] = *(sourceptr + (step + 3));
pixel[4] = *(sourceptr + (step + step - 3));
pixel[5] = *(sourceptr + step + step);
pixel[6] = *(sourceptr + (step + step + 3));
mean[4, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[4, color] = 0;
for (n = 0; n < 7; n++)
var[4, color] += pixel[n] * pixel[n] - mean[4, color] * mean[4, color];
pixel[0] = *(sourceptr - (step + step + 6));
pixel[1] = *(sourceptr - (step + step + 3));
pixel[2] = *(sourceptr - (step + 6));
pixel[3] = *(sourceptr - (step + 3));
pixel[4] = *(sourceptr - step);
pixel[5] = *(sourceptr - 3);
pixel[6] = *(sourceptr);
mean[5, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[5, color] = 0;
for (n = 0; n < 7; n++)
var[5, color] += pixel[n] * pixel[n] - mean[5, color] * mean[5, color];
pixel[0] = *(sourceptr - (step + step - 3));
pixel[1] = *(sourceptr - (step + step - 6));
pixel[2] = *(sourceptr - step);
pixel[3] = *(sourceptr - (step - 3));
pixel[4] = *(sourceptr - (step - 6));
pixel[5] = *(sourceptr);
pixel[6] = *(sourceptr + 3);
mean[6, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[6, color] = 0;
for (n = 0; n < 7; n++)
var[6, color] += pixel[n] * pixel[n] - mean[6, color] * mean[6, color];
pixel[0] = *(sourceptr);
pixel[1] = *(sourceptr + 3);
pixel[2] = *(sourceptr + step);
pixel[3] = *(sourceptr + (step + 3));
pixel[4] = *(sourceptr + (step + 6));
pixel[5] = *(sourceptr + (step + step + 3));
pixel[6] = *(sourceptr + (step + step + 6));
mean[7, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[7, color] = 0;
for (n = 0; n < 7; n++)
var[7, color] += pixel[n] * pixel[n] - mean[7, color] * mean[7, color];
pixel[0] = *(sourceptr - 3);
pixel[1] = *(sourceptr);
pixel[2] = *(sourceptr + (step - 6));
pixel[3] = *(sourceptr + (step - 3));
pixel[4] = *(sourceptr + step);
pixel[5] = *(sourceptr + (step + step - 6));
pixel[6] = *(sourceptr + (step + step - 3));
mean[8, color] = (float)(pixel[0] + pixel[1] + pixel[2] + pixel[3] + pixel[4] +
pixel[5] + pixel[6]) / 7;
var[8, color] = 0;
for (n = 0; n < 7; n++)
var[8, color] += pixel[n] * pixel[n] - mean[8, color] * mean[8, color];
descptr++;
sourceptr++;
}
min = var[0, 0] + var[0, 1] + var[0, 2];
m = 0;
for (n = 1; n < 9; n++)
{
if (min > var[n, 0] + var[n, 1] + var[n, 2])
{
min = var[n, 0] + var[n, 1] + var[n, 2];
m = n;
}
}
*(descptr - 3) = (byte)(mean[m, 0]);
*(descptr - 2) = (byte)(mean[m, 1]);
*(descptr - 1) = (byte)(mean[m, 2]);
}
sourceptr += sourcedata.Stride - source.Width * 3 + 6;
descptr += descdata.Stride - desc.Width * 3 + 6;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
4。中值滤波法
中值滤波是一种非线性平滑滤波,在一定条件下可以克服线性滤波带来的图像细节模糊问题,而且对滤除噪声干扰及图像扫描噪声非常有效。中值滤波通常采用一个含有奇数个点的滑动窗口,用窗口中各点灰度值的中值来代替中心点的灰度值。对于奇数个元素,中值是指按大小排序后中间的数值;对偶数个元素,中值是指排序后中间两个元素灰度值的平均值。
Bitmap desc = new Bitmap(source.Width, source.Height);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
byte[] mean = new byte[9];
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
mean[0] = *(sourceptr - (step + 3));
mean[1] = *(sourceptr - step);
mean[2] = *(sourceptr - (step - 3));
mean[3] = *(sourceptr - 3);
mean[4] = *(sourceptr);
mean[5] = *(sourceptr + 3);
mean[6] = *(sourceptr + (step - 3));
mean[7] = *(sourceptr + step);
mean[8] = *(sourceptr + (step + 3));
Array.Sort(mean);
*(descptr++) = mean[4];
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);
BitmapData sourcedata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData descdata = desc.LockBits(new Rectangle(0, 0, desc.Width, desc.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceptr = (byte*)sourcedata.Scan0;
byte* descptr = (byte*)descdata.Scan0;
int step = source.Width * 3;
byte[] mean = new byte[9];
for (int x = 0; x < source.Height; x++)
{
for (int y = 0; y < source.Width; y++)
{
mean[0] = *(sourceptr - (step + 3));
mean[1] = *(sourceptr - step);
mean[2] = *(sourceptr - (step - 3));
mean[3] = *(sourceptr - 3);
mean[4] = *(sourceptr);
mean[5] = *(sourceptr + 3);
mean[6] = *(sourceptr + (step - 3));
mean[7] = *(sourceptr + step);
mean[8] = *(sourceptr + (step + 3));
Array.Sort(mean);
*(descptr++) = mean[4];
sourceptr++;
}
sourceptr += sourcedata.Stride - source.Width * 3;
descptr += descdata.Stride - desc.Width * 3;
}
}
source.UnlockBits(sourcedata);
desc.UnlockBits(descdata);