高斯模糊网上例子很多,可是找了一下发现都是没有动态计算权重矩阵数组的,基本是把权重矩阵写死了
公式我就不说了,网上很多,只是没有发现权重矩阵的计算代码,根据网上的公式的推导代码
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和图片尺寸都会影响模糊效果