Delete Color

カラー画像から選択された色(背景色など)を削除します。

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

プログラムの説明

  1. カラー画像から選択された色(背景色など)を削除する image.cs のソースコードです。
    //★ クリックされた座標の色を削除する    前田 稔
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    public class MyForm : Form
    {
        Face    App;
        int     xp=0, yp=0;
        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;
            Height = App.bmp.Height+32;
    Debug.Write("Width:" + App.bmp.Width + "  Hight:" + App.bmp.Height + "  H:" + hdpi + "  V:" + vdpi + "\n");
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
        }
    
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g;
            string   str;
    
            g = e.Graphics;
            if (App.bmp == null)    Application.Exit();
            App.View(g,0,0);
            if (xp==0)  MessageBox.Show("削除する色を選択して下さい");
            else
            {
                str = "v:" + val + " [" + xp + "," + yp + "]";
                this.Text = str;
            } 
        }
    
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {   if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   if (xp==0)
                {   xp= e.X;
                    yp= e.Y;
                }
                else
                {   App.LoadImage();
                    val+= 4;
                    App.Del_Color(xp,yp,val);
                }
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();
                xp= 0;
                val= 30;
            }
            Invalidate();
        }
    }
    
    //☆ Face Object Class
    class Face
    {
        public  Bitmap  bmp = null;
        string  ImgFile = "";
        public  Color   cor_L;
        public  Color   cor_H;
    
        // Constructor
        public Face()
        {
            OpenFileDialog opendlg = new OpenFileDialog();
            opendlg.Filter = "画像ファイル|*.bmp;*.jpg|すべてのファイル|*.*" ;
            if (opendlg.ShowDialog() == DialogResult.OK)
            {   ImgFile = opendlg.FileName;
                bmp = new Bitmap(ImgFile);
            }
        }
    
        // 画像ファイルの入力
        public void LoadImage()
        {   bmp = new Bitmap(ImgFile);  }
    
        // 画像を描画
        public void View(Graphics g, int x, int y)
        {   if (bmp != null) g.DrawImage(bmp, x, y);  }
    
        // 画像から xp,yp で指定された色を削除する関数
        public void  Del_Color(int xp, int yp, int wd)
        {   if (bmp == null)    return;
            SetLimit(xp,yp,wd);
            for(int y=0; y<bmp.Height; y++)
                for(int x=0; x<bmp.Width; x++)
                {   if (ChkPic(x,y))    bmp.SetPixel(x,y,Color.Black);  }
        }
    
        // xp,yp の色を取得して cor_L ~ cor_H に設定する(wd=幅)
        public void  SetLimit(int xp, int yp, int wd)
        {   Color   cor;
            int     r,g,b;
    
            cor = bmp.GetPixel(xp,yp);
            r = cor.R-wd;
            if (r<0)    r= 0;
            g = cor.G-wd;
            if (g<0)    g= 0;
            b = cor.B-wd;
            if (b<0)    b= 0;
            cor_L = Color.FromArgb(255,r,g,b);
            r = cor.R+wd;
            if (r>255)  r= 255;
            g = cor.G+wd;
            if (g>255)  g= 255;
            b = cor.B+wd;
            if (b>255)  b= 255;
            cor_H = Color.FromArgb(255,r,g,b);
        }
    
        // xp,yp のピクセルが cor_L ~ cor_H の範囲かチェックする(範囲内=true)
        public bool  ChkPic(int xp, int yp)
        {   Color cor = bmp.GetPixel(xp,yp);
            if (cor.R<cor_L.R || cor.R>cor_H.R) return false;
            if (cor.G<cor_L.G || cor.G>cor_H.G) return false;
            if (cor.B<cor_L.B || cor.B>cor_H.B) return false;
            return true;
        }
    }
    
    class image01
    {
        [STAThread]
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. C#では BMP に限らず JPG, PNG, GIF などを使うことが出来ます。
    今回は BMP, JPG の中からファイルを選択して読み込むことにします。
            OpenFileDialog opendlg = new OpenFileDialog();
            opendlg.Filter = "画像ファイル|*.bmp;*.jpg|すべてのファイル|*.*" ;
            if (opendlg.ShowDialog() == DialogResult.OK)
            {   ImgFile = opendlg.FileName;
                bmp = new Bitmap(ImgFile);
            }
    
  3. 画像を解析する時に、背景色などが使われていると解析に支障が生じる場合があります。
    そこでマウスクリックで選択された座標からピクセルを構成する3原色を取得して背景色などを削除します。
    Select Color と逆の機能でしょうか。
    青色(B)の8ビット 緑色(G)の8ビット 赤色(R)の8ビット
    このときネックになるのが「背景色の RGB は1種類だけで無く」色が変化していることです。
    ペイントツールなどを使って背景を一色で塗りつぶすと、背景色は一色(1種類)になりますが、普通は光の状態によって色が微妙に変化します。
    そこで色の範囲を指定する閾値(しきいち)のパラメータを使います。
  4. プログラムを起動すると "削除する色を選択して下さい" のメッセージが表示されます。
    マウスの左クリックで色を選択して下さい。
    このとき画像の DPI が標準(96)以外だと座標が合わない場合があるので、Debug.Write() の印字で確認して下さい。
    続けて左クリックすると、閾値(しきいち)をアップしながら Del_Color() 関数を呼び出します。
    閾値(しきいち)が大きくなるほどカラーの部分が少なくなって黒い部分が増えます。
    マウスの右クリックで、元のカラー画像に戻ります。
        int     xp=0, yp=0;
        int     val= 30;
    
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {   if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   if (xp==0)
                {   xp= e.X;
                    yp= e.Y;
                }
                else
                {   App.LoadImage();
                    val+= 4;
                    App.Del_Color(xp,yp,val);
                }
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.LoadImage();
                xp= 0;
                val= 30;
            }
            Invalidate();
        }
    
  5. C#のプログラムは、C言語を使って作成する場合に比べて非常に簡単です。
    C言語のプログラムは Delete Color を参照して下さい。
    X,Y 座標で指定された背景色を削除する関数です。
    SetLimit(xp,yp,wd) 関数で X,Y 座標から RGB を取得して、削除する色の下限と上限を設定します。
    ChkPic() が X,Y 座標のピクセルが閾値の範囲内か超えているかを判定する関数で、範囲内の色を Black にします。
        public  Color   cor_L;          //対象となる Color の範囲
        public  Color   cor_H;
    
        // 画像から xp,yp で指定された色を削除する関数
        public void  Del_Color(int xp, int yp, int wd)
        {   if (bmp == null)    return;
            SetLimit(xp,yp,wd);
            for(int y=0; y<bmp.Height; y++)
                for(int x=0; x<bmp.Width; x++)
                {   if (ChkPic(x,y))    bmp.SetPixel(x,y,Color.Black);  }
        }
    
  6. 削除する色の下限(cor_L)と上限(cor_H)を設定する SetLimit(xp,yp,wd) 関数です。
    GetPixel(xp,yp) でピクセルを取得して、閾値を使って下限と上限を計算します。
        // xp,yp の色を取得して cor_L ~ cor_H に設定する(wd=幅)
        public void  SetLimit(int xp, int yp, int wd)
        {   Color   cor;
            int     r,g,b;
    
            cor = bmp.GetPixel(xp,yp);
            r = cor.R-wd;
            if (r<0)    r= 0;
            g = cor.G-wd;
            if (g<0)    g= 0;
            b = cor.B-wd;
            if (b<0)    b= 0;
            cor_L = Color.FromArgb(255,r,g,b);
            r = cor.R+wd;
            if (r>255)  r= 255;
            g = cor.G+wd;
            if (g>255)  g= 255;
            b = cor.B+wd;
            if (b>255)  b= 255;
            cor_H = Color.FromArgb(255,r,g,b);
        }
    
  7. X,Y 座標のピクセルが閾値(しきいち)を超えているかを判定する ChkPic() 関数です。
    超えているときは false を、範囲内に治まっているときは true をリターンします。
        // xp,yp のピクセルが cor_L ~ cor_H の範囲かチェックする(範囲内=true)
        public bool  ChkPic(int xp, int yp)
        {   Color cor = bmp.GetPixel(xp,yp);
            if (cor.R<cor_L.R || cor.R>cor_H.R) return false;
            if (cor.G<cor_L.G || cor.G>cor_H.G) return false;
            if (cor.B<cor_L.B || cor.B>cor_H.B) return false;
            return true;
        }
    

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

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