【发布时间】:2011-06-05 05:31:38
【问题描述】:
我想将图像更改为黑白或棕褐色。 转换图像后,我想用转换后的图像替换现有图像。
请给我一些建议。
【问题讨论】:
我想将图像更改为黑白或棕褐色。 转换图像后,我想用转换后的图像替换现有图像。
请给我一些建议。
【问题讨论】:
有很多方法可以去饱和彩色图像。事实上,可能没有一种“正确”或“正确”的方法可以做到这一点,尽管有些方法比其他方法更“正确”。
我假设您的图像是 RGB(红-绿-蓝)格式(尽管 BGR 也很常见)。
最简单的方法应该适用于大多数照片(但对合成图像不太适用),即只使用 3 个 RGB 通道的绿色通道。人类对光谱中绿色部分的变化最为敏感,因此绿色通道覆盖了大部分可见范围,非常接近您想要的灰度图像。
生成灰度图像的更好方法是使用 3 个 RGB 通道的加权平均值。选择相等的权重 (0.33*R+0.33*G+0.33*B) 将给出一个非常好的灰度图像。其他凸权重(总和为 1 的非负权重)将给出不同的结果,其中一些可能被认为更美观,一些可能会考虑感知参数。 (YUV uses these weights:Y = 0.299*R + 0.587*G + 0.114*B)
您始终可以将图像转换为只有一个单个灰度通道(和 2 个“颜色”通道)的颜色空间,例如 HSV(V 是灰度)、YUV(Y 是灰度)或 Lab(L 为灰度)。差异应该不会很大。
“去饱和”一词来自 HSV 空间。如果将图像转换为 HSV,将 S 通道(饱和度)设置为全零,然后渲染图像,您将获得 3 通道去饱和“彩色”图像。
将这些灰度通道复制到 RGB 中将为您提供一个 3 通道去饱和“颜色”图像 - 其中所有 3 个 RGB 通道都是相同的。
一旦您有了这张 3 通道 (RGB) 去饱和图像,您就可以将每个通道乘以一个单独的权重来为图像着色 - 棕褐色图像。
给定一个灰色像素[v,v,v],将其着色为:[v*a, v*b, v*c],这样0 <= a,b,c <=1。
【讨论】:
// Loop through the images pixels to reset color.
for(x=0; x<image1.Width; x++)
{
for(y=0; y<image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
int grayScale = (int)((originalColor.R * .3) +
(originalColor.G * .59) + (originalColor.B * .11));
//create the color object
Color newColor = Color.FromArgb(grayScale, grayScale, grayScale);
image1.SetPixel(x, y, newColor);
}
}
使用此方法将彩色像素转换为灰度
Gray = Green * 0.59 + Blue * 0.11 + Red * 0.30;
【讨论】:
对于棕褐色,您首先要转换为灰度。然后只需将每个像素乘以一组缩放三元组,例如 [1, 0.95, 0.82] 您可以使用这个三元组来获得正确的外观......所以代码可能是......
for(x=0; x<image1.Width; x++)
{
for(y=0; y<image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
int grayScale = (int)((originalColor.R * .3) + (originalColor.G * .59) + (originalColor.B * .11));
//create the color object
Color newColor = Color.FromArgb(grayScale, grayScale, grayScale);
//now apply a sepia filter
pixelColor.R = newColor.R*1;
pixelColor.G = newColor.G*0.95;
pixelColor.B = newColor.B*0.82;
image1.SetPixel(x, y, pixelColor);
}
}
【讨论】:
var color = new Bitmap("file.jpg");
var bw = color.Clone(new Rectangle(0, 0, color.Width, color.Height),
PixelFormat.Format1bppIndexed);
【讨论】:
GetPixel/SetPixel的方法很慢),而且简单,但有两个主要问题。黑/白(1 像素)转换的结果很糟糕,当源图像中有透明背景时,它会变成黑色。第二个问题是即使已经在˙color˙ 图像上调用了Dispose 方法,文件(在这种情况下为file.jpg)也会被锁定。最好在图形中使用DrawImage 方法。 (此评论不是针对 Serov Danil 的,而是针对其他程序员的)
private Bitmap grayscale(Image image)
{
Bitmap btm = new Bitmap(image);
for (int i = 0; i < btm.Width; i++)
{
for (int j = 0; j < btm.Height; j++)
{
int ser = (btm.GetPixel(i, j).R + btm.GetPixel(i, j).G + btm.GetPixel(i, j).B) / 3;
btm.SetPixel(i, j, Color.FromArgb(ser, ser, ser));
}
}
return btm;
}
【讨论】: