我正试图在android中实现一个简单的高斯模糊,但它的工作速度相当慢:(这是相关代码:
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);
}
}
如果我在帧frame_OFFSET(半径)为15的情况下使用此算法,在512x512图像上大约需要3分钟(!),并且随着偏移量的增加,情况会变得最糟。我的猜测是,这是一个缓存问题,因为当我计算新像素时,我正在访问可能不在缓存中的不同行中的像素。
如有任何帮助/改进,我们将不胜感激。
请注意,我需要自己实现这个算法,而不是使用现有的实现。
谢谢。
2D高斯模糊核是线性可分离的,这意味着它可以表示为两个1D核的外(列乘行)乘积,一个用于图像行,一个为列。因此,对于MN图像和kk内核,任何使用此属性的直接实现都应该是O(kMN),并被实现为两遍算法,每次通过都执行1D卷积,首先沿着图像行,然后沿着图像列。
在某些情况下,可以通过利用高斯核本身的某些特性来加速1D步骤,这些特性允许仅使用整数运算来增量地进行权重系数的计算。这是我所知道的最快的实现——它可以很容易地移植到Android上的Java:高斯增量计算。
使用此库:https://github.com/jrvansuita/GaussianBlur
实现方式如下:
//Asynchronous with scaleDown and changing radius
GaussianBlur.with(context).size(300).radius(10).put(R.mipmap.your_image, imageView);