为加快处理速度,在图像处理算法中,往往需要把彩色图像抓换成灰色图像,24位彩色图像每个像素用3个字节表示,每个字节对应着R、G、B分量的亮度(红、绿、蓝)。当R、G、B分量值不同是,表示为彩色图像;当R、G、B分量值相同时,表现为灰度图像,也就是求这个值。
黑白处理原理:彩色图像处理成黑白效果通常有3种算法;
(1).最大值法:使每个像素点的R,G,B值等于原像素点的RGB(颜色值)中最大的一个;
(2).平均值法:使用每个像素点的R,G,B值等于原像素点的RGB值的平均值;
(3).加权平均值法:对每个像素点的R,G,B值进行加权;
公式
一般来说,转换工式有3个。
- 第一种转换公式为:

其中,Gray(i,j)为转换后的灰度图像在(i,j)点处的灰度值。该方面虽然简单,但人眼对颜色的感应是不同的。 - 第二种转换公式:

观察上面的公司,发现绿色所占的比重最大,所以转换时可以直接使用G 值作为转换后的灰度:
Bitmap类介绍
Bitmap对象封装了GDI+中的一个位图,该位图由图形图像及其属性的像素数据组成。因此Bitmap是用于处理由像素数据定义的图像的对象。该类的主要方法和属性如下:
GetPixel方法和 SetPixel方法: 获取和设置一个图像的指定像素的颜色。
PixelFormat : 返回图像的像素格式
Palette : 获取或设置图像所使用的颜色调色板
Height 、Width : 返回图像的高度和宽度
LockBits 、UnlockBits : 分别锁定和解锁系统内存中的位图像素。
在基于像素点的图像处理方法中使用LockBits 和 UnlockBits是一个很好的方式,这两种方法可以使我们通过指定像素的范围来控制位图的任意一部分,从而消除了通过循环对位图的像素逐个进行处理的需要。每次调用LockBits之后都应该调用一次UnlockBits。
BitmapData类介绍
BitmapData对象指定了位图的属性:
Height属性,被锁定位图的高度。
Width属性,被锁定位图的宽度。
PixelFormat属性,数据的实际像素格式。
Scan0属性,被锁定数组的首字节地址。
Stride属性,步幅,也称扫描宽度。

如上图所示,数组的长度并不一定等于图像像素数组的长度,还有一部分未用区域,这涉及到位图的数据结构,系统要保证每行的字节数必须为4的倍数。
假设有一张图片宽度为6,因为是Format24bppRgb格式(每像素3字节。在以下的讨论中,除非特别说明,否则Bitmap都被认为是24位RGB)的,显然,每一行需要63=18个字节存储。
对于Bitmap就是如此。但对于BitmapData,虽然BitmapData.Width还是等于Bitmap.Width,但大概是出于显示性能的考虑,每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride。
就此例而言,18不是4的整倍数,而比18大的离18最近的4的倍数是20,所以这个BitmapData.Stride=20。
显然,当宽度本身就是4的倍数时,BitmapData.Stride=Bitmap.Width3。
BitmapData.Width*3+每行未使用空间(上图的XX)=BitmapData.Stride
图像处理的3种方法
提取像素法
该方法使用的是GDI+中的 Bitmap.GetPixel和 Bitmap.SetPixel方法。为了将位图的颜色设置为灰度或其他颜色,就需要使用GetPixel来读取当前像素的颜色,再计算灰度值,最后使用SetPixel来应用新的颜色。代码如下:
//加载图像
var curBitmap = (Bitmap)Image.FromFile(filePath);
Color curColor;
int ret;
//循环读取像素转换灰度值
for (int i = 0; i < curBitmap.Width; i++)
{
for (int j = 0; j < curBitmap.Height ; j

本文介绍了将彩色图像转换为灰度图像的三种常见算法:最大值法、平均值法和加权平均值法,并详细阐述了每种方法的实现原理。同时,讲解了Bitmap类和BitmapData类在图像处理中的作用,特别是LockBits和UnlockBits方法的使用,以及如何通过内存法和指针法提高处理速度。最后,对比了三种方法的优缺点和适用场景。

1739

被折叠的 条评论
为什么被折叠?



