Android opengles 動態調節高斯模糊

高斯模糊網上例子很多,可是找了一下發現都是沒有動態計算權重矩陣數組的,基本是把權重矩陣寫死了

公式我就不說了,網上很多,只是沒有發現權重矩陣的計算代碼,根據網上的公式的推導代碼

float a = (float) ((1.0f / 2.0f * Math.PI * Math.pow(sigma, 2.0f)) * Math.exp(-s / (2.0f * Math.pow(sigma, 2.0f))));

sigma是公式內的σ

公式有了接下來就是計算權重矩陣了

public void gaussianWeights(){
        if(blurRadius == 0 || sigma == 0){
            return;
        }
        float sumOfWeights = 0.0f;
        int g = 0;
        int tx = blurRadius*2+1;
        float gaussianWeights[] = new float[tx*tx];
        for (int x = -blurRadius; x <= blurRadius; x++) {
            for (int y = -blurRadius; y <= blurRadius; y++) {
                int s = x*x+y*y;
                float a = (float) ((1.0f / 2.0f * Math.PI * Math.pow(sigma, 2.0f)) * Math.exp(-s / (2.0f * Math.pow(sigma, 2.0f))));
                gaussianWeights[g] = a;
                sumOfWeights+=a;
                g++;
            }
        }
        for (int x = 0; x < tx*tx; ++x) {
            gaussianWeights[x] = gaussianWeights[x]/sumOfWeights;
        }
        gaussianWeightsBuffer = ByteBuffer.allocateDirect(gaussianWeights.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(gaussianWeights);
        gaussianWeightsBuffer.position(0);
    }

blurRadius是模糊半徑,當是1的時候就是一個3x3的矩陣,2的時候是5x5的矩陣,以此類推,這樣就能計算出權重矩陣的長度了

通過公式計算出來的數是大於1的數,而權重矩陣的總和是1,所以每個單位要除以總和

這樣就能得到想要的權重矩陣了

我想應該有人發現我現在的代碼都是java代碼,而不是opengles的glsl代碼,因爲glsl代碼是用來計算每一個像素的,不適合嵌套循環,如果放在glsl代碼內,那一張100x100的圖片計算3x3的權重矩陣就要進行100x100x3x3次計算,當圖片大或者權重矩陣大的時候的計算量。。

所以提出來放在cpu內進行循環,blurRadius=10的時候執行時間也才1毫秒左右,而且每次渲染只執行一次

既然算出了矩陣那就要把它傳到glsl內,所以要用到我上一篇文章了Android opengles 傳數組給shader着色器

這是效果

sigma,blurRadius和圖片尺寸都會影響模糊效果

GitHub

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章