2

I'm trying to implement a simple Gaussian blur in android and it works pretty slow :( here's the relevant code:

double rSum = 0;
double gSum = 0;
double bSum = 0;
double weightSum = 0;

for(int y = 0; y < originalImage.height ; y++){
    for(int x = 0; x < originalImage.width ; x++){
        int newPixel;

        rSum = 0;
        gSum = 0;
        bSum = 0;
        weightSum = 1;

        for(int row = y-FRAME_OFFSET ; row <= y+FRAME_OFFSET ; row++){
            for(int col = x-FRAME_OFFSET ; col <= x+FRAME_OFFSET ; col++){
                if(originalImage.inBounds(col, row)){
                    double weight = weights[(x-col)*(x-col) + (y-row)*(y-row)];
                    weightSum += weight;

                    int pixel = originalImage.at(col, row);

                    int red =  (pixel >> 16) & 0xFF ;
                    int green = (pixel >> 8) & 0xFF ;
                    int blue = pixel & 0xFF ;

                    rSum += red * weight;
                    gSum += green * weight;
                    bSum += blue * weight;  

                }
            }
        }

        rSum /= weightSum;
        gSum /= weightSum;
        bSum /= weightSum;

        newPixel = Color.rgb((int)rSum, (int)gSum, (int)bSum);                  

        maskedImage.set(x, y, newPixel);
    }
}

If i use this algorithm with frame FRAME_OFFSET (radius) of 15 it takes about 3 minutes(!) on a 512x512 image, and it get worst as i increase the offset. My guess is that it's a caching problem as when i calculate the new pixel i'm accessing pixels in different rows that's probably not in the cache.

Any help/improvements will be appreciated.

Please note that i need to implement this algorithm by myself and not use an existing implementation.

Thanks.

4

2 に答える 2

1

2D ガウスぼかしカーネルは線形分離可能です。つまり、2 つの 1D カーネル (1 つは画像の行用、もう 1 つは列用) の外側 (列×行) の積として表すことができます。したがって、このプロパティを使用する簡単な実装は、M N 画像と ak k カーネルに対して O(k M N) である必要があり、2 パス アルゴリズムとして実装する必要があります。各パスは、最初に画像行に沿って 1D 畳み込みを実行し、次に画像列に沿って。

場合によっては、ガウス カーネル自体の特定のプロパティを利用することで 1D ステップを高速化できます。これにより、重み係数の計算を整数演算のみを使用して段階的に実行できます。これは私が認識している最速の実装であり、Android 上の Java に簡単に移植できます: Incremental Computation of the Gaussian

于 2013-07-03T16:22:49.460 に答える