欢迎你们前往云+社区,获取更多腾讯海量技术实践干货哦~git
由 每天P图攻城狮 发布在云+社区
做者简介:damonxia(夏正冬),每天P图Android工程师
高斯模糊是图像处理中几乎每一个程序员都或多或少听过的名词,可是对其原理你们可能并不了解,只知道经过高斯模糊能实现图像毛玻璃效果。程序员
本文首先介绍图像处理中最基本的概念:卷积;随后介绍高斯模糊的核心内容:高斯滤波器;接着,咱们从头实现了一个Java版本的高斯模糊算法,以及实现RenderScript版本。因为咱们本身实现的Java版本的高斯模糊算法的效率过低,所以最后介绍比较有名的高斯模糊的开源项目:Blurry以及BlurKit-Android。github
BlurDemo是本文的配套Demo:算法
本文只讨论图像,而图像能够表示为二维矩阵,其中每一个元素为ARGB像素值,所以这里讨论二维矩阵的卷积操做。卷积(Convolution)是图像处理中最基本的操做,就是一个二维矩阵A(MN)和一个二维矩阵B(mn)作若干操做,生成一个新的二维矩阵C(M*N),其中m和n远小于M和N,B称为卷积核(kernel),又称滤波器矩阵或模板。框架
这里举个卷积的例子,如图:异步
上图中,最左边的是源矩阵(88),中间是卷积核(33,半径为1),最右边是经过对前面两个矩阵作卷积生成的结果矩阵。图中,若是咱们要求出结果矩阵中第二行第二列的元素的值,则把卷积核的中心元素(值为0)和源矩阵的第二行第二列(值为6)对齐,而后求加权和,即图中的公式,最后获得-3。函数
咱们再举一个例子:性能
上图也展现了如何作卷积的过程,好比要求出结果矩阵中第一行第一列的值,则把卷积核的中心对准源矩阵的第一行第一列,发现部分区域超出源矩阵的范围了(图中红色部分),解决方法有不少,这里的方案是:用边界值填充。接着作加权和,结果为-5。接着用一样的方法依次计算结果矩阵的每一个元素便可。gradle
一般来讲卷积核须要知足:优化
均值滤波器(Mean Filter)是最简单的一种滤波器,它是最粗糙的一种模糊图像的方法,高斯滤波是均值滤波的高级版本。实际上不一样的滤波器就是经过改变卷积核(滤波器),从而改变最后的结果矩阵,中间步骤都同样,都是求加权和。均值滤波器的卷积核一般是mm的矩阵,其中每一个元素为1/(m^2),能够看出卷积核的元素总和为1。好比33的均值滤波器,卷积核的每一个元素就是1/9。
高斯滤波器是均值滤波器的高级版本,惟一的区别在于,均值滤波器的卷积核的每一个元素都相同,而高斯滤波器的卷积核的元素服从高斯分布。
高斯滤波器是基于二维的高斯分布函数,所以首先介绍二维高斯分布函数。二维高斯分布函数和图以下:
其中x和y表示卷积核中某个元素横坐标和纵坐标距离中心点的距离。sigma控制曲线的平缓程度,值越大,越平缓,最高点越低。咱们能够轻易看出当x=0且y=0时值最大,即卷积核的中心点权重最大。
好比卷积核中一个元素距离中心点,横向距离2,纵向距离1,那么x=2,y=1,就能求出该元素的值。固然为了保证卷积核元素总和为1,最后每一个元素都须要除以卷积核中全部元素之和。
怎么肯定卷积核的大小呢?肯定sigma以后,虽然无论距离中心点多远,该元素的高斯分布函数值总为非负数,可是根据经验,卷积核的半径定为3sigma,所以宽高为6sigma+1。
若是高斯滤波器的卷积核是二维的(mn),则算法复杂度为O(mnMN),复杂度较高,所以接下来咱们对算法复杂度进行优化。
一维的高斯分布函数和图以下:
实际上,二维高斯分布函数能够分解为两个一维高斯分布函数相乘,以下:
所以本来的源矩阵和二维卷积核作卷积等价于源矩阵先与1m的一维卷积核作卷积,再与m1的一维卷积核作卷积。一维卷积核的半径仍定为3sigma。此时算法复杂度变为O(2mMN)。
这里实现了简单版本的高斯模糊,经过使用横向和纵向的一维高斯滤波器分别对源矩阵卷积,经过设置sigma的大小能控制图片的模糊程度,值越大越模糊。可是算法速度仍比较慢,建议直接使用RenderScript版本或直接使用成熟的开源项目。
因为代码过长,不能截图,所以直接给出Gist地址:
https://gist.github.com/xiazd...
效果以下:
RenderScript是Android提出的一个计算密集型任务的高性能框架,能并行的处理任务,他能够充分利用多核CPU和GPU,你不须要管怎么调度你的任务,只须要管任务具体作什么。这里不深刻介绍RenderScript,由于RenderScript已经提供了一个实现高斯模糊的类:ScriptIntrinsicBlur。
实现起来很是简单:
开源项目
关于Android图像模糊的开源项目有不少,好比Blurry是专门针对Bitmap或View作模糊,能够设置模糊的基底色,并且还能对模糊操做异步化;BlurKit-Android也能对Bitmap作高斯模糊(内部经过RenderScript实现),但最吸引人的是实现了毛玻璃的遮罩,效果以下:
BlurKit-Android支持的最低版本是Android 4.1(API 16),所以若是应用须要支持的最低版本是4.0,则不能使用该库,Blurry支持的最低版本是3.0。
配置过程以下:
配置完成后,经过调用BlurKit.getInstance().blur(Bitmap src, int radius);实现高斯模糊,并会把高斯模糊的结果图写入src,其中0<radius<=25。
该库还提供了fastBlur()实现速度更快的高斯模糊,和blur()的区别在于,fastBlur()在高斯模糊以前对图片采样,使得图片大小缩小好几倍,从而加快高斯模糊的速度。这种加快速度的方法是合理的,由于高斯模糊并不须要原图像很精确的信息。
BlurKit-Android最吸引人的是提供高斯模糊的遮罩(BlurLayout),随着遮罩下面的内容的变化,高斯模糊效果也会随之改变。使用以下:
该Layout可以实现实时的对该Layout下面的内容作高斯模糊。
配置方法:在build.gradle中添加compile 'jp.wasabeef:blurry:2.1.1'。
使用方法以下:
总的来讲,这两个库都使用起来很是方便。
此文已由做者受权云加社区发布,转载请注明文章出处