我比较好奇的是公式里的这些系数是怎么确定下来的
引用
评论
C#中可以用ColorMatrix进行颜色变换。ColorMatrix由一个float[][]交错数组组成,5行5列。
横行表示5个颜色源:源R、源G、源B、源Alpha、源1
纵列表示5个颜色目标:目标R、目标G、目标B、目标Alpha、目标1(忽略)
灰度化公式:light = 0.299 * r + 0.587 * g + 0.114 * b
源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
namespace grayscale
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap colorBmp;
Bitmap grayBmp;
Bitmap GetGrayScale(Bitmap src)
{
// 灰度化公式:
// light = 0.299 * r + 0.587 * g + 0.114 * b
float[][] cmatdata =
{
new float[] {0.299f, 0.299f, 0.299f, 0, 0},
new float[] {0.587f, 0.587f, 0.587f, 0, 0},
new float[] {0.114f, 0.114f, 0.114f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1},
};
ColorMatrix cmat = new ColorMatrix(cmatdata);
ImageAttributes imageattr = new ImageAttributes();
imageattr.SetColorMatrix(cmat);
Bitmap graybmp = new Bitmap(src.Width, src.Height);
Graphics.FromImage(graybmp).DrawImage(
src,
new Rectangle(0, 0, src.Width, src.Height),
0, 0, src.Width, src.Height,
GraphicsUnit.Pixel,
imageattr
);
return graybmp;
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "打开图片";
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
colorBmp = new Bitmap(ofd.FileName);
grayBmp = GetGrayScale(colorBmp);
Invalidate();
}
catch (Exception err)
{
MessageBox.Show(err.ToString() + "\r\n" + err.StackTrace);
}
}
}
private void Form_Paint(object sender, PaintEventArgs e)
{
if (grayBmp != null)
{
e.Graphics.DrawImage(grayBmp, 0, 0, grayBmp.Width, grayBmp.Height);
}
}
}
}
灰度化除了使用ColorMatrix以外,也可以自己逐个处理像素颜色,就是比较麻烦一点。除了这个公式以外,还有两个整数运算公式,分别适用于16位机和32位机:
上述整数运算适用于浮点运算能力差的处理器,实际上在现代Intel计算机上性能提升不明显。
还有一种据传是Adobe中的灰度化算法:
Adobe RGB (1998) [gamma=2.20]
light = (r ^ 2.2 * 0.2973 + g ^ 2.2 * 0.6274 + b ^ 2.2 * 0.0753) ^ (1 / 2.2)
速度慢,但是效果较好。
还有就是最简单的平均值算法,这个最原始,效果也较差。
最暴力的算法是直接拿绿色值作灰度,因为绿色最亮。