高斯模糊網上例子很多,可是找了一下發現都是沒有動態計算權重矩陣數組的,基本是把權重矩陣寫死了
公式我就不說了,網上很多,只是沒有發現權重矩陣的計算代碼,根據網上的公式的推導代碼
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和圖片尺寸都會影響模糊效果