【问题标题】:Gaussian blur in android is pretty slowandroid中的高斯模糊非常慢
【发布时间】:2013-06-30 09:22:17
【问题描述】:

我正在尝试在 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 分钟(!),并且随着我增加偏移量,它会变得最差。 我的猜测是这是一个缓存问题,因为当我计算新像素时,我正在访问可能不在缓存中的不同行中的像素。

任何帮助/改进将不胜感激。

请注意,我需要自己实现这个算法,而不是使用现有的实现。

谢谢。

【问题讨论】:

  • 你试过用traceview找瓶颈吗?
  • “我需要自己实现这个算法,而不是使用现有的实现”。我们在帮忙做作业吗?
  • 您通过为每个输出像素计算输入的 k x k 加权和,将大小为 k 的过滤器应用于大小为 NxM 的图像。即,对于每个输出像素,您正在读取它周围的 k x k 区域。所以你的算法需要 order(kkNM) 时间。只需两次通过输入数据(一次水平和一次垂直),就可以计算出高斯滤波器。这里没有足够的空间来描述它,但是请阅读有关如何实现卷积核的信息。一旦你得到正确的计算,你的算法将花费 order(2*NM) 时间。
  • 查看此链接,尤其是有关可分离过滤器的 cmets:jhlabs.com/ip/blurring.html
  • 这是另一个有用的链接:lotsacode.wordpress.com/2010/12/08/…

标签: android image-processing blur gaussian


【解决方案1】:

2D 高斯模糊内核是线性可分的,这意味着它可以表示为两个 1D 内核的外部(列乘以行)乘积,一个用于图像行,一个用于列。因此,对于 MN 图像和 akk 内核,任何使用此属性的直接实现都应该是 O(kMN),并且可以实现为两遍算法,其中每次通过执行一维卷积,首先沿着图像行,然后沿着图像列。

在某些情况下,可以通过利用高斯核本身的某些特性来加速 1D 步骤,这些特性允许仅使用整数运算以增量方式计算权重系数。这是我所知道的最快的实现——它可以很容易地移植到 Android 上的 Java:Incremental Computation of the Gaussian

【讨论】:

    【解决方案2】:

    使用这个库:https://github.com/jrvansuita/GaussianBlur

    这样实现:

    //Asynchronous with scaleDown and changing radius
    GaussianBlur.with(context).size(300).radius(10).put(R.mipmap.your_image, imageView);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2015-11-05
      • 2016-01-02
      • 2015-09-18
      相关资源
      最近更新 更多