将位图转换为灰度

Bos*_*sco 0 .net c# 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

usr*_*ΛΩΝ 6

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

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

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

您现在必须生成具有原始图像相同的宽度和高度的新图像.灰度图像的特征在于具有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;
Run Code Online (Sandbox Code Playgroud)

再次注意:这段代码类似于伪代码,我实际上没有对它进行测试.

为什么算术意味着错误?

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

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

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

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

[后续工作]我刚刚发现这篇文章有工作代码示例

编辑

既然您已经展示了一个很好的问题(并且告诉您有转换代码),请让我帮助您.如果您发布了转换代码,那会更有帮助.您必须从磁盘单独加载图像,编辑它并绑定到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;
    }
}
Run Code Online (Sandbox Code Playgroud)