灰度图像是指在黑白图像中,每个像素的颜色值表示了该像素的亮度或灰度级别,其取值范围通常为0到255,其中0代表黑色,255代表白色。
在灰度图像中,每个像素的RGB三个分量相等,因此没有彩色信息,只有亮度信息。对于二值灰度图像来说,像素值只能是0或1,灰度级别为2。而对于256级灰度的图像,像素的RGB分量相同,如RGB(100,100,100)代表灰度级别为100,RGB(50,50,50)代表灰度级别为50。
在处理图像时,我们可以单独对RGB三个分量进行处理,但实际上RGB并不能完全反映图像的形态特征,它只是从光学原理上进行颜色的调配。因此,在某些情况下,我们可能会将彩色图像转换为灰度图像,以突出亮度信息并更便于进行图像处理。
将彩色转为灰度的几种方法:
- 分量法
将彩色图像中的三分量的亮度作为三个灰度图像的灰度值,可根据应用需要选取一种灰度图像。
private async void ToolStripMenuItem_ClickAsync(object sender, EventArgs e)
{
// 读取原始图像
Bitmap originalImage = new Bitmap(imgpath);
// 创建一个新的灰度图像
Bitmap grayImage1 = new Bitmap(originalImage.Width, originalImage.Height);
Bitmap grayImage2 = new Bitmap(originalImage.Width, originalImage.Height);
Bitmap grayImage3 = new Bitmap(originalImage.Width, originalImage.Height);
// 提取R、G、B三色分量
double[,] imR = new double[originalImage.Width, originalImage.Height];
double[,] imG = new double[originalImage.Width, originalImage.Height];
double[,] imB = new double[originalImage.Width, originalImage.Height];
for (int y = 0; y < originalImage.Height; y++)
{
for (int x = 0; x < originalImage.Width; x++)
{
Color pixelColor = originalImage.GetPixel(x, y);
imR[x, y] = (double)pixelColor.R / 255.0;
imG[x, y] = (double)pixelColor.G / 255.0;
imB[x, y] = (double)pixelColor.B / 255.0;
}
}
// 同时计算三个通道的灰度图像
Task task1 = Task.Run(() =>
{
CalculateGrayImage(imR, grayImage1);
});
Task task2 = Task.Run(() =>
{
CalculateGrayImage(imG, grayImage2);
});
Task task3 = Task.Run(() =>
{
CalculateGrayImage(imB, grayImage3);
});
// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);
}
private void CalculateGrayImage(double[,] channelData, Bitmap grayImage)
{
for (int y = 0; y < grayImage.Height; y++)
{
for (int x = 0; x < grayImage.Width; x++)
{
int grayValue = (int)(channelData[x, y] * 255.0);
Color grayColor = Color.FromArgb(grayValue, grayValue, grayValue);
grayImage.SetPixel(x, y, grayColor);
}
}
}
2.最大值法
将彩色图像中的三分量亮度的最大值作为灰度图的灰度值。
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
// 读取原始图像
Bitmap originalImage = new Bitmap(imgpath);
// 创建一个新的灰度图像
Bitmap grayImage = new Bitmap(originalImage.Width, originalImage.Height);
for (int y = 0; y < originalImage.Height; y++)
{
for (int x = 0; x < originalImage.Width; x++)
{
Color color = originalImage.GetPixel(x, y);
int MaxColor = Math.Max(color.R, color.G);
MaxColor = Math.Max(color.B, MaxColor);
Color grayColor = Color.FromArgb(MaxColor, MaxColor, MaxColor);
grayImage.SetPixel(x, y, grayColor);
}
}
ShowImages(originalImage, grayImage);
}
3.平均值法
将彩色图像中的三分量亮度求平均得到一个灰度值。
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
// 读取原始图像
Bitmap originalImage = new Bitmap(imgpath);
// 创建一个新的灰度图像
Bitmap grayImage = new Bitmap(originalImage.Width, originalImage.Height);
for (int y = 0; y < originalImage.Height; y++)
{
for (int x = 0; x < originalImage.Width; x++)
{
Color color = originalImage.GetPixel(x, y);
int area = (int)(color.R + color.G + color.B) / 3;
Color grayColor = Color.FromArgb(area, area, area);
grayImage.SetPixel(x, y, grayColor);
}
}
ShowImages(originalImage, grayImage);
}
4.加权平均法
根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高, 对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。
这里使用的是人眼感知的权重int grayValue = (int)(pixelColor.R * 0.299 + pixelColor.G * 0.587 + pixelColor.B * 0.114);
-
Luma (ITU-R BT.709):grayValue = (int)(pixelColor.R * 0.2126 + pixelColor.G * 0.7152 + pixelColor.B * 0.0722)
-
Average:grayValue = (int)((pixelColor.R + pixelColor.G + pixelColor.B) / 3)
-
Lightness (HSL):grayValue = (int)((Math.Max(Math.Max(pixelColor.R, pixelColor.G), pixelColor.B) + Math.Min(Math.Min(pixelColor.R, pixelColor.G), pixelColor.B)) / 2)
-
Desaturation:grayValue = (int)((Math.Max(Math.Max(pixelColor.R, pixelColor.G), pixelColor.B) + Math.Min(Math.Min(pixelColor.R, pixelColor.G), pixelColor.B)) / 2)
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
// 读取原始图像
Bitmap originalImage = new Bitmap(imgpath);
// 创建一个新的灰度图像
Bitmap grayImage = new Bitmap(originalImage.Width, originalImage.Height);
for (int y = 0; y < originalImage.Height; y++)
{
for (int x = 0; x < originalImage.Width; x++)
{
Color pixelColor = originalImage.GetPixel(x, y);
int grayValue = (int)(pixelColor.R * 0.299 + pixelColor.G * 0.587 + pixelColor.B * 0.114);
Color grayColor = Color.FromArgb(grayValue, grayValue, grayValue);
grayImage.SetPixel(x, y, grayColor);
}
}
ShowImages(originalImage, grayImage);
}