开发者社区> 杰克.陈> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

简介: 原文:Android图像处理 - 高斯模糊的原理及实现 欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 由 天天P图攻城狮 发布在云+社区 作者简介:damonxia(夏正冬),天天P图Android工程师 前言 高斯模糊是图像处理中几乎每个程序员都或多或少听过的名词,但是对其原理大家可能并不了解,只知道通过高斯模糊能实现图像毛玻璃效果。
+关注继续查看
原文:Android图像处理 - 高斯模糊的原理及实现

欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~

由 天天P图攻城狮 发布在云+社区

作者简介:damonxia(夏正冬),天天P图Android工程师

前言

高斯模糊是图像处理中几乎每个程序员都或多或少听过的名词,但是对其原理大家可能并不了解,只知道通过高斯模糊能实现图像毛玻璃效果。

本文首先介绍图像处理中最基本的概念:卷积;随后介绍高斯模糊的核心内容:高斯滤波器;接着,我们从头实现了一个Java版本的高斯模糊算法,以及实现RenderScript版本。由于我们自己实现的Java版本的高斯模糊算法的效率太低,因此最后介绍比较有名的高斯模糊的开源项目:Blurry以及BlurKit-Android。

BlurDemo是本文的配套Demo:

  • Demo1:Java版本的高斯模糊的简单实现。
  • Demo2:RenderScript的高斯模糊实现。
  • Demo3:BlurKit-Android的基本使用。
  • Demo4:Blurry的基本使用。

卷积

本文只讨论图像,而图像可以表示为二维矩阵,其中每个元素为ARGB像素值,因此这里讨论二维矩阵的卷积操作。卷积(Convolution)是图像处理中最基本的操作,就是一个二维矩阵A(M*N)和一个二维矩阵B(m*n)做若干操作,生成一个新的二维矩阵C(M*N),其中m和n远小于M和N,B称为卷积核(kernel),又称滤波器矩阵或模板。

这里举个卷积的例子,如图:

上图中,最左边的是源矩阵(8*8),中间是卷积核(3*3,半径为1),最右边是通过对前面两个矩阵做卷积生成的结果矩阵。图中,如果我们要求出结果矩阵中第二行第二列的元素的值,则把卷积核的中心元素(值为0)和源矩阵的第二行第二列(值为6)对齐,然后求加权和,即图中的公式,最后得到-3。

我们再举一个例子:

上图也展示了如何做卷积的过程,比如要求出结果矩阵中第一行第一列的值,则把卷积核的中心对准源矩阵的第一行第一列,发现部分区域超出源矩阵的范围了(图中红色部分),解决方法有很多,这里的方案是:用边界值填充。接着做加权和,结果为-5。接着用同样的方法依次计算结果矩阵的每个元素即可。

通常来说卷积核需要满足:

  • 宽和高都为奇数,这样才会有半径和中心的概念。
  • 元素总和为1。

滤波器

均值滤波器

均值滤波器(Mean Filter)是最简单的一种滤波器,它是最粗糙的一种模糊图像的方法,高斯滤波是均值滤波的高级版本。实际上不同的滤波器就是通过改变卷积核(滤波器),从而改变最后的结果矩阵,中间步骤都一样,都是求加权和。均值滤波器的卷积核通常是m*m的矩阵,其中每个元素为1/(m^2),可以看出卷积核的元素总和为1。比如3*3的均值滤波器,卷积核的每个元素就是1/9。

高斯滤波器

高斯滤波器是均值滤波器的高级版本,唯一的区别在于,均值滤波器的卷积核的每个元素都相同,而高斯滤波器的卷积核的元素服从高斯分布。

高斯滤波器是基于二维的高斯分布函数,因此首先介绍二维高斯分布函数。二维高斯分布函数和图如下:

其中x和y表示卷积核中某个元素横坐标和纵坐标距离中心点的距离。sigma控制曲线的平缓程度,值越大,越平缓,最高点越低。我们可以轻易看出当x=0且y=0时值最大,即卷积核的中心点权重最大。

比如卷积核中一个元素距离中心点,横向距离2,纵向距离1,那么x=2,y=1,就能求出该元素的值。当然为了保证卷积核元素总和为1,最后每个元素都需要除以卷积核中所有元素之和。

怎么确定卷积核的大小呢?确定sigma之后,虽然不管距离中心点多远,该元素的高斯分布函数值总为非负数,但是根据经验,卷积核的半径定为3*sigma,因此宽高为6*sigma+1。

如果高斯滤波器的卷积核是二维的(m*n),则算法复杂度为O(m*n*M*N),复杂度较高,因此接下来我们对算法复杂度进行优化。

一维的高斯分布函数和图如下:

实际上,二维高斯分布函数可以分解为两个一维高斯分布函数相乘,如下:

因此原本的源矩阵和二维卷积核做卷积等价于源矩阵先与1*m的一维卷积核做卷积,再与m*1的一维卷积核做卷积。一维卷积核的半径仍定为3*sigma。此时算法复杂度变为O(2*m*M*N)。

高斯模糊的实现

Java版本

这里实现了简单版本的高斯模糊,通过使用横向和纵向的一维高斯滤波器分别对源矩阵卷积,通过设置sigma的大小能控制图片的模糊程度,值越大越模糊。但是算法速度仍比较慢,建议直接使用RenderScript版本或直接使用成熟的开源项目。

由于代码过长,不能截图,因此直接给出Gist地址:https://gist.github.com/xiazdong/d57bf5441f56db197163a5de69dfa65f

效果如下:

RenderScript版本

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-Android

配置过程如下:

  • 在build.gradle中设置:compile 'com.wonderkiln:blurkit:1.0.0',并在defaultConfig中设置renderscriptTargetApi 24renderscriptSupportModeEnabled true
  • 在Application的onCreate()最开始处加入BlurKit.init(this);

配置完成后,通过调用BlurKit.getInstance().blur(Bitmap src, int radius);实现高斯模糊,并会把高斯模糊的结果图写入src,其中0<radius<=25。

该库还提供了fastBlur()实现速度更快的高斯模糊,和blur()的区别在于,fastBlur()在高斯模糊之前对图片采样,使得图片大小缩小好几倍,从而加快高斯模糊的速度。这种加快速度的方法是合理的,因为高斯模糊并不需要原图像很精确的信息。

BlurKit-Android最吸引人的是提供高斯模糊的遮罩(BlurLayout),随着遮罩下面的内容的变化,高斯模糊效果也会随之改变。使用如下:

该Layout能够实现实时的对该Layout下面的内容做高斯模糊。

Blurry

配置方法:在build.gradle中添加compile 'jp.wasabeef:blurry:2.1.1'

使用方法如下:

总的来说,这两个库都使用起来非常方便。

相关阅读

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

iOS图像处理系列 - 双重曝光技术的GPUImage实现

iOS图像处理系列 - GPUImage源码解读(二)


此文已由作者授权云加社区发布,转载请注明文章出处

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
基于QProbe创建基本Android图像处理框架
先来看一个GIF   这个GIF中有以下几个值得注意的地方 这个界面是基本的主要界面所应该在的地方。其右下角有一个“+”号,点击后,打开图像采集界面 在这个界面最上面的地方,显示的是当前图像处理的状态。
903 0
(GO_GTD_3)基于OpenCV和QT,建立Android图像处理程序
一、解决权限问题     图片采集了,处理了,如何保存?最直接的方法是使用imwrite,但是如果现在直接使用的话,比如会出现这样或那样的错误,因为我们现在是在android的环境下进行图像处理,所以必须要融入到Android的权限管理系统中去。
816 0
(GO_GTD_1)基于OpenCV和QT,建立Android图像处理程序
一、创建新QT工程 一定要是全英文路径,比如“E:\android_qt_opencv\GO_GTD” 由于我们在安装的时候,选择android的工具链,所以在这里会出现以下选择,正确进行选择。   现在大家手头淘汰下来的手机都是很多了,其中不乏还可以用的。
926 0
(GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序
一、综述     如何采集图片?在windows环境下,我们可以使用dshow,在linux下,也有ffmpeg等基础类库,再不济,opencv自带的videocapture也是提供了基础的支撑。那么在andoird下,使用的肯定是Android自带的相关函数了。
830 0
OpenCV学习笔记(七)—— OpenCV for Android实时图像处理
 在上篇中我们已经实现了相机打开和实时图像信息的获取,那么接下来我们可以尝试在获取的图像信息进行一些处理,然后实时显示出来,在这里我们要完成的的几种处理:         灰化、Canny边缘检测、Hist直...
1000 0
Android Studio进行APP设计开发之矢量图及XML文件转换
Android Studio进行APP设计开发之矢量图及XML文件转换
0 0
Android studio开发APP时设置更改启动时的主界面程序
Android studio开发APP时设置更改启动时的主界面程序
0 0
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
0 0
Android开发:使用Java对手机截图图片进行任意区域的颜色对比度处理操作
开发项目过程中,对于手机屏幕截图,需要对获取到的截图的任意部分进行区域颜色对比度的识别操作,由此判定任意指定区域是否满足某对比度基本标准,但是该功能在网上任何地方都没有找到过Java方面的代码,于是根据RGB转换测试的原理:即获取每个像素点的RGB,通过RGB对比度定义公式进行像素点的集合换取。
0 0
+关注
杰克.陈
一个安静的程序猿~
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Android组件化实现
立即下载
蚂蚁聚宝Android秒级编译—— Freeline
立即下载
Android插件化:从入门到放弃
立即下载