Delete Color

画像から X,Y 座標で指定された背景色などを削除します。

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

指定された色を削除

  1. 画像を解析する時に、背景色などが使われていると解析に支障が生じる場合があります。
    そこで指定された X,Y 座標からピクセルを構成する3原色を取得して背景色を削除します。
    Select Color と逆の機能でしょうか。
    青色(B)の8ビット 緑色(G)の8ビット 赤色(R)の8ビット
    このときネックになるのが「背景色の RGB は1種類だけで無く」色が変化していることです。
    ペイントツールなどを使って背景を一色で塗りつぶすと、背景色は一色(1種類)になりますが、普通は光の状態によって色が微妙に変化します。
    そこで色の範囲を指定する閾値(しきいち)のパラメータを使います。
  2. X,Y 座標で指定された背景色を削除する関数です。
    SetLimit(x,y,wd) 関数で X,Y 座標から RGB を取得して、削除する色の下限(low)と上限(high)を設定します。
        byte        low[3];             //Color 削除の制限値
        byte        high[3];
    
    下限と上限の範囲に含まれる全てのピクセルをゼロに置き換えます。
    ChkPic() が X,Y 座標のピクセルが閾値の範囲内か超えているかを判定する関数です。
    プログラムを動かすと解るのですが、画像の座標と Dib のピクセル配置は上下が反転しています。
    VarMsg() で現在の wd の値をタイトルバーに表示しています。
    // Dib 画像から Y,X で指定された色を削除する関数
    void  IMAGEAI::Del_Color(int xp, int yp, WORD wd)
    {   int     x, y;
    
        Show(Dib.hBmpDC, 0, 0);
        SetLimit(xp,yp,wd);
    VarMsg(hWnd,"WORD WD:",wd);
        for(y=0; y<m_Height; y++)
            for(x=0; x<m_Width; x++)
            {
                if (ChkPic(x,y))
                {   MAP(y,x,0)= 0;
                    MAP(y,x,1)= 0;
                    MAP(y,x,2)= 0;
                }
            }
    }
    
  3. Dib.hBmp から X,Y 座標のピクセルを取得して、削除する色の下限と上限を設定する関数です。
    RGB は8ビット(BYTE)なので、この範囲に収まるように設定しています。
    // Dib.hBmp から X,Y の色を取得して low[3], high[3] を設定する(wd 幅)
    void  IMAGEAI::SetLimit(int x, int y, WORD wd)
    {   int     cp;
        WORD    wk;
    
        for(cp = 0; cp<3; cp++)
        {
            wk= MAP(y,x,cp);
            if (wk>wd)  low[cp]= wk-wd;
            else    low[cp]= 0;
            wk+= wd;
            if (wk>255) wk= 255;
            high[cp]= (BYTE)wk;
        }
    }
    
  4. X,Y 座標のピクセルが閾値(しきいち)の範囲内か超えているかを判定する ChkPic() 関数です。
    超えているときは false を、範囲内に治まっているときは true をリターンします。
    // X,Y のピクセルが low[3] から high[3] の範囲かチエックする 
    bool  IMAGEAI::ChkPic(int x, int y)
    {   if (MAP(y,x,0)<low[0])  return false;
        if (MAP(y,x,0)>high[0]) return false;
        if (MAP(y,x,1)<low[1])  return false;
        if (MAP(y,x,1)>high[1]) return false;
        if (MAP(y,x,2)<low[2])  return false;
        if (MAP(y,x,2)>high[2]) return false;
        return true;
    }
    
  5. wd の値をタイトルバーに表示する VarMsg() 関数です。
    ImageAI.h では宣言していないので、コンストラクタの直前に置いて下さい。
    void  VarMsg(HWND hwnd, char *msg, WORD n)
    {   char    str[80];
        wsprintf(str,"%s=%d\n",msg,n);
        SetWindowText(hwnd,(LPCSTR)str);
    }
    
  6. Main.cpp の AppInit() から OpenFile() で画像ファイルを選択します。
    InitDib() で DibStruct を初期化して下さい。
    SetRGB(7) で最初は画像の色を本来の色に設定して描画します。
    // 画像をロードして、24bit DIB を作成
    LRESULT  AppInit(HWND hwnd)
    {
        ImageAI= new IMAGEAI(hwnd);
        if (ImageAI->OpenFile()==false) return false;
        ImageAI->InitDib();
        ImageAI->SetRGB(7);
        return true;
    }
    
  7. WM_LBUTTONDOWN: では、閾値の領域を定義して、マウスのクリックで値をアップします。
    WORD    wd= 10;                 // 閾値
            ・・・
            case WM_LBUTTONDOWN:    // 左ボタンをクリック
                wd= wd+2;
                // X,Y の色を削除
                ImageAI->Del_Color(0,0,wd);
                InvalidateRect(hWnd,NULL,FALSE);
                break;
    
  8. WM_PAINT では、加工した画像を Dib.hBmpDC から描画します。
            case WM_PAINT:          // Dib の画像を描画
                hdc = BeginPaint(hWnd,&ps);
                if (ImageAI)   ImageAI->ShowDib(hdc,30,20);
                EndPaint(hWnd, &ps);
                break;
    
  9. 果物の画像はデジカメで撮影したものをサイズを縮小しました。
    Main.cpp の基本ソースコードは Image 3原色 を参照して下さい。
    ImageAI Class のソースコードは Color ⇒ Grayscale を参照して下さい。

[Next Chapter ↓] Select Color
[Previous Chapter ↑] Color ⇒ Binary Mode

超初心者のプログラム入門(Win32API C++)