Line をピックアップ

エッジを検出して作成した二値画像から Line をピックアップします。

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

プログラムの説明

  1. image.cs のソースコードは Color ⇒ エッジ画像 に準じます。
    ページ先頭の画像は draw.gif で、C#で入力すると Index Color モードで格納されます。
    Index Color モードに対して GetPixel(), SetPixel() は使えません。
    従って draw.gif を使うときは24ビット BMP 形式に変換して下さい。
  2. 閾値 val は Line を検出する長さを指定します。
    ウインドウサイズは画像サイズに合わせて少し大きめに設定しました。
        Face    App;
        int     val= 20;        // 閾値
        public MyForm()
        {
            App = new Face();
            App.edge = (Bitmap)App.bmp.Clone();
            Width = App.bmp.Width+16;
            Height = App.bmp.Height+42;
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
        }
    
  3. マウスの左クリックで val をアップしながら、エッジ画像から Line をピックアップします。
    App.Edge(33000) でカラー画像からエッジを検出して二値画像を作成します。
    App.HLine(val) でエッジの画像から横線をピックアップします。
    App.VLine(val) でエッジの画像から縦線をピックアップします。
    左クリックする度に短い横線が検出されなくなります。
    マウスの右クリックで、元のカラー画像に戻します。
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   val += 10;
                App.Edge(33000);
                App.HLine(val);
                App.VLine(val);
                VerMsg("val: ", val);
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   App.edge = (Bitmap)App.bmp.Clone();
                val= 20;
            }
            Invalidate();
    
  4. 横線を調べて edge 画像に Red(赤色)の線を設定する関数です。
    edge.GetPixel(x,y) で黒のピクセルが検出されると、右方向に長さを調べて val より長いときは赤色に設定します。
        // 横線を調べて edge 画像に Red を設定する
        public void  HLine(int val)
        {   Color   cor;
            int     x,y,wk;
    
            for(y=1; y<bmp.Height-1; y++)
                for(x=1; x<bmp.Width-1; x++)
                {   cor = edge.GetPixel(x,y);
                    if (cor.R==0)
                    {   for(wk=x; wk<edge.Width-1; wk++)
                        {   cor = edge.GetPixel(wk,y);
                            if (cor.R!=0)   break;
                        }
                        if ((wk-x)>val)
                        {   cor = Color.Red;
                            for(wk--; wk>=x; wk--)  edge.SetPixel(wk,y,cor);
                        }
                    }
                }
        }
    
  5. 縦線を調べて edge 画像に Green(緑色)の線を設定する関数です。
    edge.GetPixel(x,y) で緑がゼロのピクセルが検出されると、下方向に長さを調べて val より長いときは緑色に設定します。
    GetPixel() の座標系は、左上を起点とするディスプレイ座標です。
    一般の写真の画像でも、横線,縦線が検出されることを確かめて下さい。
        // 縦線を調べて edge 画像に Green を設定する
        public void  VLine(int val)
        {   Color   cor;
            int     x,y,wk;
    
            for(x=1; x<bmp.Width-1; x++)
                for(y=1; y<bmp.Height-1; y++)
                {   cor = edge.GetPixel(x,y);
                    if (cor.G==0)
                    {   for(wk=y; wk<edge.Height-1; wk++)
                        {   cor = edge.GetPixel(x,wk);
                            if (cor.G!=0)   break;
                        }
                        if ((wk-y)>val)
                        {   cor = Color.Green;
                            for(wk--; wk>=y; wk--)  edge.SetPixel(x,wk,cor);
                        }
                    }
                }
        }
    

Line() 関数

  1. 関数にパラメータを設定して、45度の斜線も検出できるようにします。
    App.Line(1,0,val) が横線で、App.Line(0,1,val) が縦線です。
    App.Line(1,1,val) が右下がりの斜線で、App.Line(1,-1,val) が右上がりの斜線です。
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   val += 10;
                App.Edge(33000);
                App.Line(1,0,val);
                App.Line(0,1,val);
                App.Line(1,1,val);
                App.Line(1,-1,val);
                VerMsg("val: ", val);
            }
    
  2. 45度の斜線も検出できる Line() 関数です。
    dx がX軸方向の増分で、dy がY軸方向の増分です。
    cnt で Line が途切れるまでのループ回数をカウントします。
        // Line を検出して edge 画像に Red を設定する
        public void  Line(int dx, int dy, int val)
        {   Color   cor;
            int     x,y,wx,wy,cnt;
    
            for(x=1; x<bmp.Width-1; x++)
                for(y=1; y<bmp.Height-1; y++)
                {   cor = edge.GetPixel(x,y);
                    if (cor.R==0)
                    {   wx = x;
                        wy = y;
                        for(cnt=0; ; cnt++,wx+=dx,wy+=dy)
                        {   if (wx<0 || wx>=bmp.Width || wy<0 || wy>=bmp.Height) break;
                            cor = edge.GetPixel(wx,wy); 
                            if (cor.R!=0)   break;
                        }
                        if (cnt>val)
                        {   cor = Color.Red;
                            wx = x;
                            wy = y;
                            for(; cnt>=0; cnt--,wx+=dx,wy+=dy)
                            {   edge.SetPixel(wx, wy, cor);  }
                        }
                    }
                }
        }
    

float 関数

  1. パラメータが int タイプでは、任意の斜線に対応出来ません。
    そこで dx, dy を float で渡します。
    dx, dy を調整することで、様々な斜線に対応します。
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {   val += 10;
                App.Edge(33000);
                App.Line(1, (float)0.6, val);
                App.Line(1,(float)-0.6,val);
                App.Line(1,(float)1.2,val);
                App.Line(1,(float)-1.2,val);
                VerMsg("val: ", val);
            }
    
  2. 任意の斜線をピックアップ出来る Line() 関数です。
    dx がX軸方向の増分で、dy がY軸方向の増分です。
    cnt で Line が途切れるまでのループ回数をカウントします。
        // float で Line を調べて edge 画像に Red を設定する
        public void  Line(float dx, float dy, int val)
        {   Color   cor;
            int     x,y,cnt,ix,iy;
            float   wx,wy;
    
            for(x=1; x<bmp.Width-1; x++)
                for(y=1; y<bmp.Height-1; y++)
                {   cor = edge.GetPixel(x,y);
                    if (cor.R==0)
                    {   wx = x;
                        wy = y;
                        for(cnt=0; (int)wy>0; cnt++,wx+=dx,wy+=dy)
                        {   ix = (int)wx;
                            iy = (int)wy;
                            if (ix < 0 || ix >= bmp.Width || iy < 0 || iy >= bmp.Height) break;
                            cor = edge.GetPixel((int)wx,(int)wy); 
                            if (cor.R!=0)   break;
                        }
                        if (cnt>val)
                        {   cor = Color.Red;
                            wx = x;
                            wy = y;
                            for(; cnt>=0; cnt--,wx+=dx,wy+=dy)
                            {   edge.SetPixel((int)wx,(int)wy,cor);  }
                        }
                    }
                }
        }
    

[Next Chapter ↓] BitBlt
[Previous Chapter ↑] Color ⇒ エッジ画像

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