01.<span style="font-family:Microsoft YaHei;">/// 获取灰度值返回byte[]
02./// <summary>
03./// 获取灰度值返回byte[]
04./// </summary>
05./// <param name="srcBmp">源图像</param>
06./// <param name="rect">要锁定的图像区域</param>
07./// <returns>返回byte[]</returns>
08.public static byte[] GetGrayArray(Bitmap srcBmp, Rectangle rect)
09.{
10. //将Bitmap锁定到系统内存中
11. //rect是指源图像中需要锁定那一块矩形区域进行处理
12. //ImageLockMode.ReadWrite是指对图像出操作的权限,枚举有只读,只写,用户输入缓冲区,还是读写
13. //PixelFormat.Format24bppRgb
14. //参数确定了该图像信息时rgb存储还是Argb存储,如果是Format24ppRgb则处理的图像像素就是BGR方式存储,我们这里没有特别指出,均是Format24bppRgb方式存储处理
15. BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
16. //位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
17. IntPtr srcPtr = srcBmpData.Scan0;
18. //将Bitmap对象的信息存放到byte数组中
19. //假设本图像的宽度和高度为5*3
20. /*
21. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //这里存储为一维数组,所以是一行,
22. 宽度为5,高度为3,则像素总数为15,这里要清楚,每一个像素是rgb三个值,故而,一维数组中
23. 存储为
24. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
25. 15...44
26. 这里分行是为了便于理解,一维数组存储类似是一行,但是我们的图像的宽度是5也就是我们图像的第一行是0123...到14,下一行是15...29,下一行是30...44,高度为3,所以就是3行
27. 012 345 678 91011 121314
28. bgr bgr bgr bgr bgr
29. 151617 181920 ...
30. bgr bgr ...
31. 这样存储
32. */
33. //所以才有了这里的*3就是指一个像素是三个分量值
34. int scanWidth = rect.Width * 3;
35. //而每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride,如果上面的第三个参数Format24ppRgb如果设置为Format32ppRgb,
这个时候存储的时候就是4位存储一个像素,如果是Format32bppArgb同样也是4为存储一个像素,这4位除了bgr三个分量之外还有透明度A的值
36. //至于为什么是24,32,这是因为计算机存储数据为8bit存储1个字节,
37. //bgr3个就是3*8=24,4个就是4*8=32了,为什么是16,8位等,索引图等原理是一样的
38. //int srcStride = srcBmpData.Stride;
39. int src_bytes = scanWidth * rect.Height; //这里就是计算出了需要存储的像素所占用的空间大小
40. byte[] srcValues = new byte[src_bytes]; //定义源图像的元信息
41. byte[] grayValues = new byte[rect.Width * rect.Height]; //定义转化为灰度后需要存储的数组
42. //复制GRB信息到byte数组,将从srcPtr开始的第一个扫描行开始扫描信息,然后读取到srcValues数组中
43. Marshal.Copy(srcPtr, srcValues, 0, src_bytes);
44. //解锁位图
45. srcBmp.UnlockBits(srcBmpData); //读取完元信息,这里就不用了,一定要记得解锁,否则会报错
46. //下面就是你想怎么处理都成了,,灰度化,转换空间模式,除噪声,腐蚀,膨胀,反色,二值化等等均可
47. //灰度化处理
48. int m = 0, j = 0;
49. int k = 0;
50. byte gray;
51. //根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像
52. //根据Y = 0.299*R + 0.587*G + 0.114*B //加权平均法
53. for (int i = 0; i < rect.Height; i++)
54. {
55. for (j = 0; j < rect.Width; j++)
56. {
57. //注意位图结构中RGB按BGR的顺序存储
58. k = 3 * j;
59. gray = (byte)(srcValues[i * scanWidth + k + 2] * 0.299
60. + srcValues[i * scanWidth + k + 1] * 0.587
61. + srcValues[i * scanWidth + k + 0] * 0.114);
62. grayValues[m] = gray; //将灰度值存到double的数组中
63. m++;
64. }
65. }
66. return grayValues;
67.}
68.
69.//接下来就很简单了,下面在给出获得到灰度值存储为2位数组的方法,按照习惯二维处理起来比较好理解
70./// 获取灰度值存到二维double数组中,这个是将rgb转化为灰度值
71./// <summary>
72./// 获取灰度值存到二维double数组中,这个是将rgb转化为灰度值
73./// </summary>
74./// <param name="srcBmp"></param>
75./// <returns>2Dimension</returns>
76.public static byte[,] GetGrayArray2D(Bitmap srcBmp,Rectangle rect)
77.{
78. int width = rect.Width;
79. int height = rect.Height;
80.
81. BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
82.
83. IntPtr srcPtr = srcBmpData.Scan0;
84.
85. int scanWidth = width * 3;
86. int src_bytes = scanWidth * height;
87. //int srcStride = srcBmpData.Stride;
88. byte[] srcRGBValues = new byte[src_bytes];
89. byte[,] grayValues = new byte[height, width];
90. //RGB[] rgb = new RGB[srcBmp.Width * rows];
91. //复制GRB信息到byte数组
92. Marshal.Copy(srcPtr, srcRGBValues, 0, src_bytes);
93. //解锁位图
94. srcBmp.UnlockBits(srcBmpData);
95. //灰度化处理
96. int m = 0, i = 0, j = 0; //m表示行,j表示列
97. int k = 0;
98. byte gray;
99.
100. for (i = 0; i < height; i++) //只获取图片的rows行像素值
101. {
102. for (j = 0; j < width; j++)
103. {
104. //只处理每行中图像像素数据,舍弃未用空间
105. //注意位图结构中RGB按BGR的顺序存储
106. k = 3 * j;
107. gray = (byte)(srcRGBValues[i * scanWidth + k + 2] * 0.299
108. + srcRGBValues[i * scanWidth + k + 1] * 0.587
109. + srcRGBValues[i * scanWidth + k + 0] * 0.114);
110.
111. grayValues[m, j] = gray; //将灰度值存到double的数组中
112. }
113. m++;
114. }
115.
116. return grayValues;
117.}
118.
119.//此方法是直接得到灰度图
120./// 获取灰度图像,将制定图片转化为灰度图
121./// <summary>
122./// 获取灰度图像,将制定图片转化为灰度图
123./// </summary>
124./// <param name="srcBmp"></param>
125./// <returns></returns>
126.public static Bitmap GetGrayImage(Bitmap srcBmp)
127.{
128. Rectangle rect = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
129. BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
130. IntPtr srcPtr = srcBmpData.Scan0;
131. int scanWidth = srcBmpData.Width * 3;
132. int src_bytes = scanWidth * srcBmp.Height;
133. byte[] srcRGBValues = new byte[src_bytes];
134. Marshal.Copy(srcPtr, srcRGBValues, 0, src_bytes);
135. //灰度化处理
136. int k = 0;
137. for (int i = 0; i < srcBmp.Height; i++)
138. {
139. for (int j = 0; j < srcBmp.Width; j++)
140. {
141. k = j * 3;
142. //0.299*R + 0.587*G + 0.144*B = 亮度或灰度
143. //只处理每行中图像像素数据,舍弃未用空间
144. //注意位图结构中RGB按BGR的顺序存储
145. byte intensity = (byte)(srcRGBValues[i * scanWidth + k + 2] * 0.299
146. + srcRGBValues[i * scanWidth + k + 1] * 0.587
147. + srcRGBValues[i * scanWidth + k + 0] * 0.114);
148. srcRGBValues[i * scanWidth + k + 0] = intensity;
149. srcRGBValues[i * scanWidth + k + 1] = intensity;
150. srcRGBValues[i * scanWidth + k + 2] = intensity;
151. }
152. }
153. Marshal.Copy(srcRGBValues, 0, srcPtr, src_bytes);
154. //解锁位图
155. srcBmp.UnlockBits(srcBmpData);
156. return srcBmp;
157.}</span>