DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

画像をグレースケールに変換して表示する

注意:画像の表示方法が分からないという方は、まず「コントロールやフォームに画像を表示する」をご覧ください。

グレースケールとは、白から黒までの明暗(つまり、灰色の濃淡)だけで画像を表現する方法です。

< グレースケール > Le Premier Soleil」によると、画像をグレースケールに変換する方法はいくつかありますが、ここではNTSC規格の白黒テレビなどで使われているYIQのYコンポーネントを使用することにします。

早速ですが、ColorMatrixクラスを使用して、指定した画像からグレースケール画像を作成する例を示します。このコードはフォームクラスに書かれており、フォームにはPictureBoxコントロール(PictureBox1)が配置されているものとします。PictureBox1をクリックすると、画像ファイル(C:\test\1.bmp)をグレースケールに変換した画像が表示されます。

なおColorMatrixクラスについては、「画像のカラーバランスを補正して表示する」で詳しく説明しています。また、ColorMatrixクラス以外の方法でグレースケールに変換することもできますが、その方法についてもそちらを参考にしてください。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

''' <summary>
''' 指定した画像からグレースケール画像を作成する
''' </summary>
''' <param name="img">基の画像</param>
''' <returns>作成されたグレースケール画像</returns>
Public Shared Function CreateGrayscaleImage(ByVal img As Image) As Image
    'グレースケールの描画先となるImageオブジェクトを作成
    Dim newImg As New Bitmap(img.Width, img.Height)
    'newImgのGraphicsオブジェクトを取得
    Dim g As Graphics = Graphics.FromImage(newImg)

    'ColorMatrixオブジェクトの作成
    'グレースケールに変換するための行列を指定する
    Dim cm As New System.Drawing.Imaging.ColorMatrix( _
        New Single()() { _
            New Single() {0.299F, 0.299F, 0.299F, 0, 0}, _
            New Single() {0.587F, 0.587F, 0.587F, 0, 0}, _
            New Single() {0.114F, 0.114F, 0.114F, 0, 0}, _
            New Single() {0, 0, 0, 1, 0}, _
            New Single() {0, 0, 0, 0, 1} _
        })
    'ImageAttributesオブジェクトの作成
    Dim ia As New System.Drawing.Imaging.ImageAttributes()
    'ColorMatrixを設定する
    ia.SetColorMatrix(cm)

    'ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _
                0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)

    'リソースを解放する
    g.Dispose()

    Return newImg
End Function

'PictureBox1のClickイベントハンドラ
Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles PictureBox1.Click
    'グレースケールにする画像
    Dim img As New Bitmap("C:\test\1.bmp")
    'グレースケールに変換
    Dim glayImg As Image = CreateGrayscaleImage(img)
    img.Dispose()
    'PictureBox1に表示
    If Not PictureBox1.Image Is Nothing Then
        PictureBox1.Image.Dispose()
    End If
    PictureBox1.Image = glayImg
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

/// <summary>
/// 指定した画像からグレースケール画像を作成する
/// </summary>
/// <param name="img">基の画像</param>
/// <returns>作成されたグレースケール画像</returns>
public static Image CreateGrayscaleImage(Image img)
{
    //グレースケールの描画先となるImageオブジェクトを作成
    Bitmap newImg = new Bitmap(img.Width, img.Height);
    //newImgのGraphicsオブジェクトを取得
    Graphics g = Graphics.FromImage(newImg);

    //ColorMatrixオブジェクトの作成
    //グレースケールに変換するための行列を指定する
    System.Drawing.Imaging.ColorMatrix cm =
        new System.Drawing.Imaging.ColorMatrix(
            new float[][]{
                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}
            });
    //ImageAttributesオブジェクトの作成
    System.Drawing.Imaging.ImageAttributes ia =
        new System.Drawing.Imaging.ImageAttributes();
    //ColorMatrixを設定する
    ia.SetColorMatrix(cm);

    //ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img,
        new Rectangle(0, 0, img.Width, img.Height),
        0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);

    //リソースを解放する
    g.Dispose();

    return newImg;
}

//PictureBox1のClickイベントハンドラ
private void PictureBox1_Click(object sender, EventArgs e)
{
    //グレースケールにする画像
    Bitmap img = new Bitmap(@"C:\test\1.bmp");
    //グレースケールに変換
    Image glayImg = CreateGrayscaleImage(img);
    img.Dispose();
    //PictureBox1に表示
    if (PictureBox1.Image != null)
    {
        PictureBox1.Image.Dispose();
    }
    PictureBox1.Image = glayImg;
}

結果は、次のようになります。上が元の画像で、下がグレースケールにした画像です。

グレースケール

Matrix Operations for Image Processing」によると、上記のYIQの方法はガンマ値が2.2の時に最適であり、そうでない時は0.3086、0.6094、0.0820という値を使った方がよいということです。

この値にして上記のメソッドを書き直すと、次のようになります。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

''' <summary>
''' 指定した画像からグレースケール画像を作成する
''' </summary>
''' <param name="img">基の画像</param>
''' <returns>作成されたグレースケール画像</returns>
Public Shared Function CreateGrayscaleImage(ByVal img As Image) As Image
    'グレースケールの描画先となるImageオブジェクトを作成
    Dim newImg As New Bitmap(img.Width, img.Height)
    'newImgのGraphicsオブジェクトを取得
    Dim g As Graphics = Graphics.FromImage(newImg)

    'ColorMatrixオブジェクトの作成
    'グレースケールに変換するための行列を指定する
    Dim cm As New System.Drawing.Imaging.ColorMatrix(New Single()() _
        {New Single() {0.3086F, 0.3086F, 0.3086F, 0, 0}, _
         New Single() {0.6094F, 0.6094F, 0.6094F, 0, 0}, _
         New Single() {0.082F, 0.082F, 0.082F, 0, 0}, _
         New Single() {0, 0, 0, 1, 0}, _
         New Single() {0, 0, 0, 0, 1}})
    'ImageAttributesオブジェクトの作成
    Dim ia As New System.Drawing.Imaging.ImageAttributes()
    'ColorMatrixを設定する
    ia.SetColorMatrix(cm)

    'ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _
                0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)

    'リソースを解放する
    g.Dispose()

    Return newImg
End Function
C#
コードを隠すコードを選択
//using System.Drawing;

/// <summary>
/// 指定した画像からグレースケール画像を作成する
/// </summary>
/// <param name="img">基の画像</param>
/// <returns>作成されたグレースケール画像</returns>
public static Image CreateGrayscaleImage(Image img)
{
    //グレースケールの描画先となるImageオブジェクトを作成
    Bitmap newImg = new Bitmap(img.Width, img.Height);
    //newImgのGraphicsオブジェクトを取得
    Graphics g = Graphics.FromImage(newImg);

    //ColorMatrixオブジェクトの作成
    //グレースケールに変換するための行列を指定する
    System.Drawing.Imaging.ColorMatrix cm =
        new System.Drawing.Imaging.ColorMatrix(
            new float[][]{
        new float[]{0.3086f, 0.3086f, 0.3086f, 0 ,0},
        new float[]{0.6094f, 0.6094f, 0.6094f, 0, 0},
        new float[]{0.0820f, 0.0820f, 0.0820f, 0, 0},
        new float[]{0, 0, 0, 1, 0},
        new float[]{0, 0, 0, 0, 1}
    });
    //ImageAttributesオブジェクトの作成
    System.Drawing.Imaging.ImageAttributes ia =
        new System.Drawing.Imaging.ImageAttributes();
    //ColorMatrixを設定する
    ia.SetColorMatrix(cm);

    //ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img,
        new Rectangle(0, 0, img.Width, img.Height),
        0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);

    //リソースを解放する
    g.Dispose();

    return newImg;
}

結果は、次のようになります。上の画像が書き直した方法によるもので、下の画像が以前の方法によるものです。

グレースケールの比較

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。