将位图转换为灰度

时间:2011-01-17 22:41:33

标签: c# .net image-processing

我有一个WinForm应用程序,我想在一个直接转换为灰度的图片框中加载一个位图(.bmp)。我有关于如何加载和过滤图像的代码,我还有转换图像的代码......但我不知道如何将它们连接到工作程序

private void btnLoad_Click(object sender, EventArgs e) 
{
    OpenFileDialog fDialog = new OpenFileDialog();
    fDialog.Filter = "Bitmaps |*.bmp| GIFs |*.gif| JPEGs |*.jpg;*.jpeg| TIFs |*.tif";
    fDialog.InitialDirectory = @"C:\\";
    if (fDialog.ShowDialog() == DialogResult.OK)
    {
        pcbImage.Image = Image.FromFile(fDialog.FileName);
        pcbImage.SizeMode = PictureBoxSizeMode.StretchImage;
    }
}

1 个答案:

答案 0 :(得分:6)

您的问题表明您对图像和.NET Framework非常困惑。

根据我的回答,我不会为您提供代码,因为它需要一些额外的时间,但我想帮助您提出建议。这是算法,编码将取决于你。

首先,使用Image类将图像作为RGB。加载图像后,您将拥有由像素组成的结构,每个结构都包含三个组件RGB。如果我从基础开始,请不要被冒犯,但我不知道你的实际经验水平。

您现在必须使用原始图像的相同宽度和高度生成新图像。灰度图像的特点是具有R==G==B,这意味着新图像必须使每个像素的所有3个值相同。

为了获得该值,您有很多选择:常见选项(大多数错误)是执行算术平均值,即。 C = (R+G+B)/3(你必须对它进行三次,每个组件一次)。我稍后会告诉你为什么这个选择是错误的,但却被普遍接受。

以下是适用于您的伪代码

Image old;
old = Image.Load("file.bmp"); //I don't currently have MSDN at hand, nor I remember how to load the bitmap
Image new = new Image{ Width = old.Width; Height = old.Height };
for (i=0; i<old.Width-1; i++)
    for (j=0; j<old.Height; j++)
    {
        Color p = old[i,j];
        byte gray = (p.R+p.G+p.B)/3;
        new[i,j] = new Color(gray,gray,gray);
    }
 }
 pictureBox.Image = new;

再次注意:此代码类似于伪代码,我实际上并没有测试它。

为什么算术意味着错误?

(问题中最有趣的部分,从科学角度来看)

灰度图像基于亮度的概念,其是由物体反射并施加在亮度传感器(即灰度相机)上的光的能量。彩色自然光由具有宽光谱的电磁波组成,但常见的传感器仅由红色绿色蓝色的频率触发>光谱。人眼也对绿色比其他人更敏感(我的图表显示人眼对不同频率的光线的反应)。

这意味着假设三个灯光组件提供相等对亮度有贡献是错误的,就像当你向观众展示两个相同功率的灯,一个过滤绿色和一个过滤蓝色,观察者会告诉你绿色更亮。

有一个转换表(如果我发现它,我稍后会更新帖子),它会显示如何使用适当的系数执行加权平均值来处理此现象。此外,已发现通过此表格转换的图像看起来比使用常规均值转换的其他图像更逼真

[后续行动]我刚发现this article有工作代码示例

修改

既然您已经展示了一个很好的问题(并告诉您拥有转换代码),请让我帮助您。如果您发布了转换代码,那会更有帮助。您必须从磁盘中单独加载您的图片,编辑,然后绑定到PictureBox。

假设您有private Image ConvertToGrayscale(Image source);,以下是适合您的代码:

private void btnLoad_Click(object sender, EventArgs e) 
{
    OpenFileDialog fDialog = new OpenFileDialog();
    fDialog.Filter = "Bitmaps |*.bmp| GIFs |*.gif| JPEGs |*.jpg;*.jpeg| TIFs |*.tif";
    fDialog.InitialDirectory = @"C:\\";
    if (fDialog.ShowDialog() == DialogResult.OK)
    {
        Image old = Image.FromFile(fDialog.FileName);
        pcbImage.Image = ConvertToGrayscale(old);
        pcbImage.SizeMode = PictureBoxSizeMode.StretchImage;
    }
}