Color ⇒ 二値画像

カラー画像を二値画像に変換します。

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

プログラムの説明

  1. カラー画像を二値画像に変換する image.cs のソースコードです。
    //★ Binary Mode で描画    前田 稔
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    public class MyForm : Form
    {
        Face    App;
        int     val= 30;
        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.LoadImage();
                val+= 2;
                App.BinMode(val);
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();
                val= 30;
            }
            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);
        }
    
        // Binary Mode で描画
        public void BinMode(int val)
        {   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;
                    if (wk < val) cor = Color.Black;
                    else cor = Color.White;
                    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ビット
    これを白黒2階調の二値画像に変換します。
    二値画像はグレースケールやエッジ画像と共に画像を解析するときに役に立ちます。
  3. C#のプログラムは、C言語を使って作成する場合に比べて非常に簡単です。
    C言語のプログラムは 二値画像に変換 及び Binary Mode を参照して下さい。
    C言語では CreateDIBSection() 関数でピクセルデーターの配列にアクセスしているのですが、C#ではこれに相当する関数が見つかりません。
    そこで Bitmap 画像からピクセルを取得する GetPixel() 関数と、ピクセル毎に色を設定する SetPixel() 関数を使って作成します。
    これを使えばプログラムは簡単で解り易いのですが、難点は実行速度が遅いことでしょうか?
  4. ピクセル毎にアクセスして、二値画像に変換するソースコードです。
    RGB を単純に加えて3で割る方法では、色に対する明るさが考慮されていません。
    そこでウエイトを掛けて演算しています。
    val は二値画像の閾値(しきいち)で値が大きくなるほど、黒のピクセルが増えます。
        // Binary Mode で描画
        public void BinMode(int val)
        {   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;
                    if (wk < val) cor = Color.Black;
                    else cor = Color.White;
                    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. マウスの左クリックで val をアップしながら二値画像に変換します。
    左クリックの度に BinMode() 関数を呼び出すのですが、実行速度が遅く反応が遅れるので間を置いてクリックして下さい。
    マウスの右クリックで val を最初の値に戻して、元のカラー画像に設定します。
        int     val= 30;    // 閾値
    
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   App.LoadImage();
                val+= 2;
                App.BinMode(val);
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();
                val= 30;
            }
            Invalidate();
        }
    

[Next Chapter ↓] Delete Color
[Previous Chapter ↑] Color ⇒ Grayscale

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