Color ⇒ Grayscale

カラー画像をグレースケールに変換します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. カラー画像をグレースケールに変換する image.cs のソースコードです。
    //★ Grayscale で描画    前田 稔
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    public class MyForm : Form
    {
        Face    App;
        public MyForm()
        {
            BackColor = SystemColors.AppWorkspace;
            App = new Face();
            float hdpi = App.bmp.HorizontalResolution;
            float vdpi = App.bmp.VerticalResolution;
            Width = App.bmp.Width*96/(int)hdpi;
            Height = (App.bmp.Height+32)*96/(int)vdpi;
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
        }
    
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g; 
            g = e.Graphics;
            if (App.bmp == null)    Application.Exit();
            App.View(g,0,0);
        }
    
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   App.Gray();  }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();  }
            Invalidate();
        }
    }
    
    //☆ Face Object Class
    class Face
    {
        public  Bitmap  bmp = null;
        string  ImgFile = "";
    
        // Constructor
        public Face()
        {
            OpenFileDialog opendlg = new OpenFileDialog();
            opendlg.Filter = "画像ファイル (*.bmp)|*.bmp|すべてのファイル (*.*)|*.*" ;
            if (opendlg.ShowDialog() == DialogResult.OK)
            {   ImgFile = opendlg.FileName;  }
            try
            {   bmp = new Bitmap(ImgFile);  }
            catch
            {   MessageBox.Show("画像ファイルが読めません!", ImgFile);
                return ;
            }
        }
    
        // 画像ファイルの入力
        public void LoadImage(string file)
        {
            bmp = new Bitmap(file);
        }
        public void LoadImage()
        {
            LoadImage(ImgFile);
        }
    
        // 画像を描画
        public void View(Graphics g, int x, int y)
        {
            if (bmp != null) g.DrawImage(bmp, x, y);
        }
    
        // Grayscale で描画
        public void Gray()
        {   Color   cor;
            Int32   wk;
            byte    R,G,B;
    
            if (bmp == null)    return;
            for(int y=0; y<bmp.Height; y++)
                for(int x=0; x<bmp.Width; x++)
                {   cor = bmp.GetPixel(x,y);
                    R = cor.R;
                    G = cor.G;
                    B = cor.B;
                    wk = (B*2 + G*4 + R) / 7;
                    cor = Color.FromArgb(wk, wk, wk);
                    bmp.SetPixel(x,y,cor);
                }
        }
    }
    
    class image01
    {
        [STAThread]
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. カラー画像は RGB をそれぞれ8ビットで記録されています。
    青色(B)の8ビット 緑色(G)の8ビット 赤色(R)の8ビット
    これをグレースケールの「256階調に変換」すると画像解析が少しは楽になります。 (^_^;)
    少し工夫すれば「セピア色(RGB=107,74,43)」の画像も作成することが出来ます。
  3. C#のプログラムは、C言語を使って作成する場合に比べて非常に簡単です。
    C言語のプログラムは カラー ⇒ グレースケール を参照して下さい。
    C言語では CreateDIBSection() 関数でピクセルデータの配列にアクセスしているのですが、C#ではこれに相当する関数が見つかりません。
    そこで Bitmap 画像からピクセルを取得する GetPixel() 関数と、ピクセル毎に色を設定する SetPixel() 関数を使って作成します。
    これを使えばプログラムは簡単で解り易いのですが、難点は実行速度が遅いことでしょうか?
    GetPixel(), SetPixel() 関数は、左上を起点とするディスプレイ座標系です。
    Win32 API を使って、実行が速いプログラムは W32 Color ⇒ Gray を参照して下さい。
  4. ピクセル毎にアクセスして、グレースケールに変換するソースコードです。
    RGB を単純に加えて3で割る方法では、色に対する明るさが考慮されていません。
    そこでウエイトを掛けて演算しています。
        // Grayscale で描画
        public void Gray()
        {   Color   cor;
            Int32   wk;
            byte    R,G,B;
    
            if (bmp == null)    return;
            for(int y=0; y<bmp.Height; y++)
                for(int x=0; x<bmp.Width; x++)
                {   cor = bmp.GetPixel(x,y);
                    R = cor.R;
                    G = cor.G;
                    B = cor.B;
                    wk = (B*2 + G*4 + R) / 7;
                    cor = Color.FromArgb(wk, wk, wk);
                    bmp.SetPixel(x,y,cor);
                }
        }
    
  5. MyForm Class のコンストラクタでは Face Class を生成して画像を入力します。
    画像サイズに合わせてウインドウサイズを設定します。
        public MyForm()
        {
            BackColor = SystemColors.AppWorkspace;
            App = new Face();
            float hdpi = App.bmp.HorizontalResolution;
            float vdpi = App.bmp.VerticalResolution;
            Width = App.bmp.Width*96/(int)hdpi;
            Height = (App.bmp.Height+32)*96/(int)vdpi;
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
        }
    
  6. MyHandler() では、View() 関数を呼び出して画像を描画します。
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g; 
            g = e.Graphics;
            if (App.bmp == null)    Application.Exit();
            App.View(g,0,0);
        }
    
  7. マウスの左クリックで Gray() 関数を呼び出して、カラー画像をグレースケールに変換します。
    マウスの右クリックで元のカラー画像に戻します。
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   App.Gray();  }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();  }
            Invalidate();
        }
    

[Next Chapter ↓] Color ⇒ 二値画像
[Previous Chapter ↑] Face Image

超初心者のプログラム入門(C# Frame Work)