专栏首页天天P图攻城狮Android图像处理系列 - 高斯模糊的几种优化方法

Android图像处理系列 - 高斯模糊的几种优化方法

一,高斯模糊简介

高斯模糊是图像处理中常用的一种操作,用于减少图像细节,平滑图像。简单来说,高斯模糊的处理过程,是让图像每个像素都取周边像素的平均值,是参照正态分布的加权平均值。

比如kernel为3*3的高斯模糊,就是取每个像素周围8个点再加上该像素的加权平均值,每个点的权重如图1。

图1 kernel为3的高斯模糊,每点权重值

高斯模糊每个点的权重分配以正态分布为依据。一维正态分布函数

函数图像如图2。

图2 一维标准正态分布

不同的

,对应不同的函数图像,如图3。另外正态分布函数中

。高斯模糊实现时,如何选择

,如何根据给定的模糊半径确定有限个采样点的权重,都是需要解决的问题,不过并不在本文讨论范围之内。

图3 不同的正态分布

二维正态分布函数

图4 二维正态分布图像

可以看出,二维正态分布函数,等于x方向和y方向的两个一维正态分布函数的乘积。

高斯模糊的实现,一般不会直接对m*m范围内的点计算加权平均,这种方式的时间复杂度为O(n*n*m*m),这里假设传入图像大小为n*n,kernel为m。较常见的做法是,分别在x方向和y方向,各做一次加权平均。时间复杂度可以降低到O(n*n*m)。

二,box blur:cpu上的快速实现

高斯模糊要求距离中心点越近的点,权重越高,越远则权重越低。如果所有点权重一样,则无法得到平滑的模糊效果。

但是,权重相同的模糊操作,重复多次之后,也可以得到类似高斯模糊的效果。这就是box blur。Box blur与高斯模糊的效果比较如图5。

图5 box blur与高斯模糊效果比较

从一维角度观察,box blur对数值的改变情况如图6所示。依次是经过一次box blur,经过两次box blur和经过三次box blur的结果。

图6 box blur多次处理结果比较

Box blur重复三次,与高斯模糊的差异在3%以内。效果上非常接近。

Box blur的最大优势,在于计算相同权重平均数,可以使用滑动窗口方法。Box blur的时间复杂度为O(n*(n+m)),因为一般m<<n,所以增大模糊半径,对box blur的耗时影响很小。

如果用CPU实现高斯模糊效果,box blur应该是最高效的算法,还可以利用多线程进一步提高box blur的速度。不过对于移动端GPU,使用OpenGL接口,较难使用滑动窗口方法计算平均数,所以box blur的优势在GPU上较难体现出来。

三,利用GPU线性插值减少采样次数

GPU做高斯模糊,常用的优化方法之一,是利用texture采样时的线性插值,来减少采样次数和计算次数。

Texture采样的线性插值操作如图7所示。

图7 texture采样线性插值

a,b,c,d是texture上相邻的四个点,如果从texture上采样,传入的e点的坐标刚好在a,b之间,那么取得的值为a、b两点的加权平均值

,。如果e位于a、b、c、d之间,则e的值是a、b、c、d四点双线性插值的结果。Texture采样时的线性插值操作,由GPU硬件默认完成,效率较高。

利用线性插值可以做到一次采样得到两个点的值,加快高斯模糊的计算速度。例如图8。

图8 利用线性插值减少采样次数

假设做横向的加权平均,中心点为c,c点左右各取两个点,每个点的权重如图所示。

c’ = 0.625a + 0.25b + 0.375c + 0.25d + 0.625e。

a点和b点本来各需做一次采样,利用线性插值,在b点左侧0.625/(0.625+0.25)个点距的位置采样,得到的结果就是(0.625a + 0.25b)/(0.625+0.25)。同理d和e的加权和也可以用一次采样得到。原来共需要5次采样,现在只需要3次。

利用上述方法,大体上可以让高斯模糊采样次数减半,效率提升明显。不过,这种方法只是利用一次采样获取两个点的值,而一次采样最多可以得到四个点的值。所以在利用GPU线性插值这一点上,是否有更快的实现高斯模糊的方法?答案是肯定的,那就是Kawase blur。

Kawase blur利用一次采样获取四个点的值,每一次处理做4次采样,进行多次处理,最终得到近似于高斯模糊的结果。如图9,Kawase blur通过5次处理,可以得到类似kernel size为35的高斯模糊的效果。

图9 kernel依次为0,1,2,2,3的Kawase blur

图中的灰色方格表示texture中的一个像素,蓝色点表示采样位置。红色方格表示当前要计算平均和的点。规定这5次处理的Kawase blur kernel,依次是0,1,2,2,3。可以通过这样一个数组来描述特定次数和kernel的Kawase blur。

下图是从一维角度,比较kernel 为35的高斯模糊,和上述(0,1,2,2,3)的Kawase blur在处理结果上的差异。

图10 左:kernel为35的高斯模糊。右:(0,1,2,2,3)的Kawase blur

下图是两种模糊算法处理实际图片的结果比较。依次是原图,高斯模糊处理结果,Kawase blur处理结果。

图11 Kawase blur与高斯模糊效果对比

效率上面,kernel为35的高斯模糊,使用线性插值的优化方法,每个点的采样次数为18*2=36次,(0,1,2,2,3)的Kawase blur的采样次数仅为4*5=20次。图12是不同硬件,不同kernel的高斯模糊与Kawase blur处理时间比。可以看出Kawase blur比高斯模糊速度更快。高斯模糊的处理时间会随kernel增大而线性增加,Kawase blur的处理时间随着kernel增大,似乎会以低于线性的速度增加。

图12 Kawase blur与高斯模糊运行时间对比

Kawase blur的主要限制在于,对任意的高斯模糊kernel,没有方法可以直接得到对应的Kawase blur的kernel list。

四,缩小图片

高斯模糊另一个常见的优化方法,是对图片进行缩小,然后再做模糊,最后再把图片放大到原来尺寸。

缩小图片往往有丢失图像细节的问题,而高斯模糊的作用在于平滑地降低图像细节。所以可以利用缩小图片的方法,减少计算量同时几乎不影响最终效果。

常见做法是缩小图片-->高斯模糊-->放大图片,但这样容易出现一个问题,当缩小比例较大时,小图高斯模糊之后,图像会有锯齿。

解决方法,N次缩小,每次缩小到原来的1/4并伴随一次(固定kernel的)模糊,在最终的小图上再做一次kernel为K的模糊。N和K与要达到的高斯模糊kernel有关。

这种方法可以避免锯齿,时间复杂度上也比标准高斯模糊更快,标准高斯模糊每个点上的计算量与kernel成正比。这种缩小模糊的方法,每个点的计算量估计与kernel的对数成正比。在kernel比较大时,这种方法效率提升明显。

参考文献

1)https://en.wikipedia.org/wiki/Gaussian_blur

2)https://en.wikipedia.org/wiki/Box_blur

3)https://prolost.com/blog/2006/3/2/a-tale-of-three-blurs.html

4)https://software.intel.com/en-us/blogs/2014/07/15/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms

5)http://www.daionet.gr.jp/~masa/archives/GDC2003_DSTEAL.ppt

6)https://www.google.com/patents/US7397964


作者简介:camusli(李小奇),天天P图Android工程师

文章分享自微信公众号:
天天P图攻城狮

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!

作者:camusli(李小奇)
原始发表时间:2017-10-18
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • Android图像处理 - 高斯模糊的原理及实现

    本文首先介绍图像处理中最基本的概念:卷积;随后介绍高斯模糊的核心内容:高斯滤波器;接着,我们从头实现了一个Java版本的高斯模糊算法,以及实现RenderScr...

    天天P图攻城狮
  • SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(二)。

          相关链接: 高斯模糊算法的全面优化过程分享(一)      在高斯模糊算法的全面优化过程分享(一)一文中我们已经给出了一种相当高性能的高斯模糊过程,...

    用户1138785
  • SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(一)。

         这里的高斯模糊采用的是论文《Recursive implementation of the Gaussian filter》里描述的递归算法。 ? ...

    用户1138785
  • Java实现高斯模糊和图像的空间卷积

    其中r是模糊半径,r^2 = x^2 + y^2,σ是正态分布的标准偏差。在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。分布不为零的像...

    fengzhizi715
  • 封装个 Android 的高斯模糊组件基础理论二次封装

    最近基于 Android StackBlur 开源库,根据自己碰到的需求场景,封装了个高斯模糊组件,顺便记录一下。

    请叫我大苏
  • 音视频开发之旅(39)- 高斯模糊实现与优化

    我们在平时的开发中模糊是非常常用的技能,在android中有java的开源方案,也有RenderScript方案,今天我们来学习实践通过OpenGL如何实现高斯...

    音视频开发之旅
  • iOS 图像处理系列 - 基于GPUImage的滤镜实现及优化

    我们知道,对于图像处理中,滤镜效果是一种最普遍也最有效的图像优化方式。通过对图像进行不同的滤镜效果的处理,可以得到各种绚丽的图片。

    天天P图攻城狮
  • Android性能优化实战之界面卡顿

    作者:红橙Darren https://www.jianshu.com/p/18bb507d6e62

    用户1269200
  • 【干货】计算机视觉实战系列06——用Python做图像处理

    【导读】专知成员Hui上一次为大家介绍主成分分析(PCA)、以及其在图像上的应用,这一次为大家详细讲解SciPy库的使用以及图像高斯模糊实战。 【干货】计算机视...

    WZEARW
  • 图像卷积与滤波参考资料:

    首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,...

    keloli
  • 滤波器——BoxBlur均值滤波及其快速实现

    在数字图像处理的语境里,图像一般是二维或三维的矩阵,卷积核(kernel)和滤波器(filter)通常指代同一事物,即对图像进行卷积或相关操作时使用的小矩阵,尺...

    李拜六不开鑫
  • 【干货】计算机视觉实战系列07——用Python做图像处理

    这一次继续为大家详细讲解SciPy库的使用以及图像导数实战。

    WZEARW
  • o(1)复杂度之双边滤波算法的原理、流程、实现及效果。

    一、引言     双边滤波在图像处理领域中有着广泛的应用,比如去噪、去马赛克、光流估计等等,最近,比较流行的Non-Local算法也可以看成是双边滤波的一种...

    用户1138785
  • Android OpenGL ES(四)-为平面图添加滤镜

    之前我们通过YUV数据格式的处理知道,只要保留Y的数据,就是灰度的图片。但是OpenGL中处理的是RGB格式的数据,我们要如何去取得灰度图呢? 我们可以通过公...

    deep_sadness
  • 基于边缘保留滤波实现人脸磨皮的算法

    快速边缘保留滤波是通过积分图像实现局部均方差的边缘保留模糊算法,计算简单而且可以做到计算量跟半径无关。 首先局部均方差滤波中计算局部均值的公式如下:

    fengzhizi715
  • OpenCV图像噪声与去噪函数方法对比使用介绍

    图像去噪在二值图像分析、OCR识别预处理环节中十分重要,最常见的图像噪声都是因为在图像生成过程中因为模拟或者数字信号受到干扰而产生的,常见的噪声类型有如下:

    OpenCV学堂
  • opencv中滤波函数的介绍和应用

    滤波作用 图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪 声(包括高斯噪声、椒盐、噪声、随机噪声等)进行抑制,是图像预 处理中不可缺少的操作,其处理效...

    zls365
  • 2d游戏shader(效果)

    刚刚开源了自己积累的一些2D效果的Shader实现,项目GitHub地址。效果在下面列出,我使用的Unity版本是5.3.5p8(当前已更新到5.6.0f3),...

    全栈程序员站长

扫码关注腾讯云开发者

领取腾讯云代金券