转自:图像处理:椒盐噪声(杂点)
Posted on 2008-10-28 16:07 parker 阅读(2794) 评论(0) 编辑 收藏1.效果图:
2.实现原理:
在处理每一个像素点时,取得一个随机值与指定的杂点出现概率的值进行判断,以决定是否修改当前像素点的颜色值,如果需要修改,则设定一个随机的颜色值。
3.实现代码:
1
/// <summary>2
/// 添加杂点3
/// </summary>4
/// <param name="img">原始图像</param>5
/// <param name="degree">指定杂点出现的概率</param>6
/// <returns></returns>7
public static Image SaltNoise(Image img, int degree)8
{9
//设定概率在0--10010
if (degree > 100) degree = 100;11
if (degree < 0) degree = 0;12

13
int width = img.Width;14
int height = img.Height;15

16
Rectangle rect = new Rectangle(0, 0, width, height);17
PixelFormat pf = PixelFormat.Format32bppArgb;18

19
//锁定Bitmap在内存中20
Bitmap bmp = new Bitmap(img); 21
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadWrite, pf);22

23
unsafe //不安全模式24
{25
//图像中第一个像素数据的地址26
byte* p = (byte*)data.Scan0;27
28
Random rand = new Random();29

30
for (int i = 0; i < height; i++)31
{32
for (int j = 0; j < width; j++)33
{34
if (rand.Next(0, 100) < degree)35
{36
p[2] = (byte)rand.Next(0, 255);37
p[1] = (byte)rand.Next(0, 255);38
p[0] = (byte)rand.Next(0, 255);39
}40
p += 4; //见下面说明41
}42
}43

44
}45
//从系统内存解锁此 Bitmap46
bmp.UnlockBits(data);47
//返回修改后的图像48
return (Image)bmp;49
}1
/// <summary>2
/// 添加杂点3
/// </summary>4
/// <param name="img">原始图像</param>5
/// <param name="degree">指定杂点出现的概率</param>6
/// <returns></returns>7
public static Image SaltNoiseMirco(Image img, int degree)8
{9
//设定概率在0---10010
if (degree < 0) degree = 0;11
if (degree > 100) degree = 100;12

13
//取得原始图像的高宽值14
int width = img.Width;15
int height = img.Height;16

17
//实例一个Bitmap18
Bitmap bmp = new Bitmap(img);19

20
Rectangle rect = new Rectangle(0, 0, width, height);21
PixelFormat format = PixelFormat.Format32bppArgb;22

23
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);24

25
IntPtr ptr = data.Scan0;26

27
//申明固定长度的数组,以存放图像数据28
int numBytes = width * height * 4;29
byte[] rgbValues = new byte[numBytes];30

31
//将图像数据从非托管内存指针复制到托管的数组32
Marshal.Copy(ptr, rgbValues, 0, numBytes);33

34
Random rand = new Random();35

36
//修改符合条件的颜色值37
for (int i = 0; i < numBytes; i +=4)38
{39
if (rand.Next(0, 100) < degree)40
{41
rgbValues[i] = (byte)rand.Next(0, 255);42
rgbValues[i + 1] = (byte)rand.Next(0, 255);43
rgbValues[i + 2] = (byte)rand.Next(0, 255); 44
}45
}46

47
//将图像数据从托管的数组复制到非托管内存指针48
Marshal.Copy(rgbValues, 0, ptr, numBytes);49
bmp.UnlockBits(data);50

51
return (Image)bmp;52
53
}4.程序说明:
A.利用LockBits方法做图像处理效率明显高于利用GetPixel方法和SetPixel方法,可比较与柔化(平滑)处理。
B.关于"方法一"
(1)编译时可能会出现错误提示“不安全代码只会在使用 /unsafe 编译的情况下出现”,处理如下:
右击项目选择"属性"-->"生成"-->勾选"允许不安全代码"-->"保存"。
(2)p += 4:
由于PixelFormat format = PixelFormat.Format32bppArgb;
指定图像中每个像素的颜色数据的格式为每像素 32 位;alpha、红色、绿色和蓝色分量各使用 8 位。
所以图像像素颜色值的存储用4个字节,分别表示B、G、R、A,各占一个字节,
p[0]:B、 p[1]:G、 p[2]:R、 p[3]:A,p+=4表示到当前像素的下一个像素的开始位置。
C.关于"方法二"
(1)Marshal.Copy()将图像数据从非托管内存指针复制到托管的数组,避免使用不安全代码。
(2)int numBytes = width * height * 4;
存放图像像素数据的数组长度 = 总像素数 * 每个像素所占的字节数。