2値画像の収縮膨張処理

孤立点の除去を行う収縮・膨張処理は以下のようにします。
対象は2値画像であるとします。また、以下の例では画像は1列の配列として扱っています。
また、収縮と膨張を行う回数は同じでなければなりません。
除去したい孤立点の広さに応じて繰り返しこの関数を呼び出します。
複数回の収縮・膨張処理を施す場合、直前の収縮・膨張処理結果に対して次の収縮・膨張処理を行うので、パラメータで処理回数を指定する関数にすると間違えやすくなります。
また、4隅の点、隅の4辺と、場合分けを行わないと、領域外を処理してしまいます。

//膨張処理
void Inflate( Byte *btData, int nRow, int nCol )
{
    LONG i, j;
    Byte *btOut = new BYTE[nRow*nCol];

    for ( i = 0; i < nRow; i++ )
    {
        for ( j = 0; j < nCol; j++ )
        {
            btOut[i*nCol + j] = btData[i*nCol + j];
            if ( i == 0 )    //上の列の場合
            {
                if ( j == 0 )    //左上角の場合
                {
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                }
                else if ( j == nCol-1 )    //右上角の場合
                {
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                }
                else    //それ以外の場合
                {
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                }
            }
            else if ( i == nRow - 1 )    //下の列の場合
            {
                if ( j == 0 )    //左下角の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                }
                else if ( j == nCol-1 )    //右下角の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                }
                else    //それ以外の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                }
            }
            else
            {
                if ( j == 0 )    //左の列の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                }
                else if ( j == nCol-1 )    //右の列の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                }
                else    //中の場合
                {
                    if ( btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 255;
                    if ( btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 255;
                }
            }
        }
    }

    for ( i = 0; i < nRow; i++ )
    {
        for ( j = 0; j < nCol; j++ )
        {
            btData[i*nCol+j] = btOut[i*nCol+j];
        }
    }

    delete btOut;
}

//収縮処理
void Deflate( BYTE *btData, int nRow, int nCol )
{
    LONG i, j;
    BYTE *btOut = new BYTE[nRow*nCol];

    for ( i = 0; i < nRow; i++ )
    {
        for ( j = 0; j < nCol; j++ )
        {
            btOut[i*nCol + j] = btData[i*nCol + j];
            if ( i == 0 )    //上の列の場合
            {
                if ( j == 0 )    //左上角の場合
                {
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                }
                else if ( j == nCol-1 )    //右上角の場合
                {
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                }
                else    //それ以外の場合
                {
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                }
            }
            else if ( i == nRow - 1 )    //下の列の場合
            {
                if ( j == 0 )    //左下角の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                }
                else if ( j == nCol-1 )    //右下角の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                }
                else    //それ以外の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                }
            }
            else
            {
                if ( j == 0 )    //左の列の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                }
                else if ( j == nCol-1 )    //右の列の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                }
                else    //中の場合
                {
                    if ( !btData[(i-1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j-1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i  )*nCol + (j+1)] ) btOut[i*nCol+j] = 0;
                    if ( !btData[(i+1)*nCol + (j  )] ) btOut[i*nCol+j] = 0;
                }
            }
        }
    }

    for ( i = 0; i < nRow; i++ )
    {
        for ( j = 0; j < nCol; j++ )
        {
            btData[i*nCol+j] = btOut[i*nCol+j];
        }
    }

    delete btOut;
}

参考文献

アーカイブ