图像转换:灰度到彩色






4.19/5 (19投票s)
简易转换图像的算法
介绍
这是一个简单的图像转换算法,将灰度图像转换为彩色图像。它远非理想,但非常简单。
背景
通常,我们计算灰度颜色如下:
Gray = Green * 0.59 + Blue * 0.30 + Red * 0.11;
每个颜色结构为 [Gray, Gray, Gray] 都有一个颜色集合
G = [Gray, Gray, Gray]
G -> P = {C},对于P中的每个C:Green * 0.59 + Blue * 0.30 + Red * 0.11 = Gray。
首先,我们创建一个控制点集合。控制点等同于“灰度”颜色和“完全”颜色。当我们设置了控制点后,可以将任何“灰度”颜色近似为“完全”颜色。如果“灰度”颜色位于两个控制点 C1 和 C2 之间,则颜色近似为:
K = (Gray - C1Gray)/(C2Gray - C1Gray)
Red = C1Red + K*(C2Red - C1Red)
Green = C1Green + K*(C2Green - C1Green)
Blue = C1Blue + K*(C2Blue - C1Blue)
现在我们为每个“灰度”颜色都获得了“完全颜色”的等效值。
图 1. 转换示意图。
使用方法
ControlPoint
是一个用于存储控制点数据的结构体。
public struct ControlPoint
{
private int level;
public int Level
{
get { return level; }
set { level = value; }
}
private Color color;
public Color Color
{
get { return color; }
set { color = value; }
}
public ControlPoint(int level, Color color)
{
this.color = color;
this.level = level;
}
public override string ToString()
{
return "Level: " + level.ToString() + "; Color: " + color.ToString();
}
}
PointsComparer
是一个用于比较两个控制点的类。
public class PointsComparer: IComparer<ControlPoint>
{
#region IComparer<ControlPoint> Members
public int Compare(ControlPoint x, ControlPoint y)
{
if (x.Level > y.Level)
{
return 1;
}
if (x.Level < y.Level)
{
return -1;
}
return 0;
}
#endregion
}
ColorBuilder
是一个用于构建颜色图表的类。它返回一个包含 256 种颜色的数组 - 我们的图表。
public static Color[] GetColorDiagram(List<ControlPoint> points)
{
Color[] colors = new Color[256];
points.Sort(new PointsComparer());
for (int i = 0; i < 256; i++)
{
ControlPoint leftColor = new ControlPoint
(0, GetNearestLeftColor(points[0].Color));
ControlPoint rightColor = new ControlPoint
(255, GetNearestRigthColor(points[points.Count - 1].Color));
if (i < points[0].Level)
{
rightColor = points[0];
}
if (i > points[points.Count - 1].Level)
{
leftColor = points[points.Count - 1];
}
else
{
for (int j = 0; j < points.Count - 1; j++)
{
if ((points[j].Level <= i) & (points[j + 1].Level > i))
{
leftColor = points[j];
rightColor = points[j + 1];
}
}
}
if ((rightColor.Level - leftColor.Level) != 0)
{
double koef = (double)(i - leftColor.Level) /
(double)(rightColor.Level - leftColor.Level);
int r = leftColor.Color.R + (int)(koef *
(rightColor.Color.R - leftColor.Color.R));
int g = leftColor.Color.G + (int)(koef *
(rightColor.Color.G - leftColor.Color.G));
int b = leftColor.Color.B + (int)(koef *
(rightColor.Color.B - leftColor.Color.B));
colors[i] = Color.FromArgb(r, g, b);
}
else
{
colors[i] = leftColor.Color;
}
}
return colors;
}
现在我们可以获得彩色图像了
colorBitmap = new Bitmap(sourceBitmap);
for (int i = 0; i < sourceBitmap.Width; i++)
{
for (int j = 0; j < sourceBitmap.Height; j++)
{
int level = sourceBitmap.GetPixel(i, j).B;
colorBitmap.SetPixel(i, j, colors[level]);
}
}
pbxColorImage.Image = colorBitmap;
图 2. 简单的颜色对话框。
图 3. 灰度图像、彩色图像和颜色图表。
值得关注的点
该算法非常简单,并且存在许多缺陷。但对于图像处理初学者来说,这是一个很好的例子。
更新信息
- 新的灰度级别计算公式
- 移除了空列表的错误