2

Sobel 演算子を使用したエッジ検出に問題があります。偽のエッジが多すぎます。下の図にその影響が示されています。私は 3x3 の sobel 演算子を使用しています。最初に垂直方向を抽出してから水平方向に抽出し、最終的な出力は各フィルター出力の大きさです。合成画像のエッジは適切に抽出されますが、ぼかしやメディアン フィルターを適用して画像を前処理しても、自然画像には誤ったエッジや「ノイズ」が多すぎます。これの原因は何ですか?実装の問題ですか (では、なぜ合成画像が良いのでしょうか?) それとも、さらに前処理を行う必要がありますか?

オリジナル:
元の

出力:
アウト

コード:

void imageOp::filter(image8* image, int maskSize, int16_t *mask)
{
    if((image == NULL) || (maskSize/2 == 0) || maskSize < 1)
    {
        if(image == NULL)
        {
            printf("filter: image pointer == NULL \n");
        }
        else if(maskSize < 1)
        {
            printf("filter: maskSize must be greater than 1\n");
        }
        else
        {
            printf("filter: maskSize must be odd number\n");
        }
        return;
    }

    image8* fImage = new image8(image->getHeight(), image->getWidth());
    uint16_t sum = 0;
    int d = maskSize/2;
    int ty, tx;

    for(int x = 0; x < image->getHeight(); x++)         //
    {                                                   // loop over image
        for(int y = 0; y < image->getWidth(); y++)      // 
        {
            for(int xm = -d; xm <= d; xm++)
            {
                for(int ym = -d; ym <= d; ym++)
                {
                    ty = y + ym;
                    if(ty < 0)  // edge conditions
                    {
                        ty = (-1)*ym - 1;
                    }
                    else if(ty >= image->getWidth())
                    {
                        ty = image->getWidth() - ym;
                    }

                    tx = x + xm;
                    if(tx < 0)  // edge conditions
                    {
                        tx = (-1)*xm - 1;
                    }
                    else if(tx >= image->getHeight())
                    {
                        tx = image->getHeight() - xm;
                    }

                    sum += image->img[tx][ty] * mask[((xm+d)*maskSize) + ym + d];
                }
            }

            if(sum > 255)
            {
                fImage->img[x][y] = 255;
            }
            else if(sum < 0)
            {
                fImage->img[x][y] = 0;
            }
            else
            {
                fImage->img[x][y] = (uint8_t)sum;
            }
            sum = 0;
        }
    }


    for(int x = 0; x < image->getHeight(); x++)
    {
        for(int y = 0; y < image->getWidth(); y++)
        {
            image->img[x][y] = fImage->img[x][y];
        }
    }

    delete fImage;
}
4

1 に答える 1

4

これは、コードのどこかにある数学エラーが原因のようです。私のコメントをフォローするために、これは、ここでSobel演算子を使用して画像を実行したときに得られるものです(エッジ強度は出力画像の明るさで示されます)。

Sobel演算子の後の画像

GLSLフラグメントシェーダーを使用してこれを作成しました。

 precision mediump float;

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 void main()
 {
    float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
    float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
    float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
    float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
    float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
    float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
    float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
    float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
    float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
    float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

    float mag = length(vec2(h, v));

    gl_FragColor = vec4(vec3(mag), 1.0);

マスク値は表示されません。これには、Sobelカーネルが含まれていると思います。上記のコードでは、3x3Sobelカーネルの各ピクセルの赤チャネルに対して実行される計算をハードコーディングしました。これは純粋に私のプラットフォームでのパフォーマンスのためです。

あなたのコードで私が気付いていないことの1つ(合計を0に戻したように、私はそれを見逃しているかもしれません)は、Sobel演算子の2つの部分のベクトルの大きさの決定です。もしそれがあれば、どこかで平方根演算が見られると思います。

于 2012-11-13T17:09:11.773 に答える