效果图:


参考了c++的高斯模糊的算法 高斯模糊的C++实现(Gaussian Blur),改成了Java版本的和ndk版本的,对比了下效果,Java的效率比较低,用时几十秒,ndk才不到1秒,毕竟安卓是Linux内核,c++跟接近底层。

原理

图像是颜色矩阵组成的,通过改变每个像素点的rgb的颜色值,可以改变图像。
图片模糊就是把像素点的rgb的值取周围像素点的加权平均值,使像素点失去其特性。
高斯模糊(英语:Gaussian Blur),也叫高斯平滑。
正态分布一维表达式:

二维是2个一维函数的积分:

这种计算方式时间复杂度大,这里试了下另一种高效的方法,对一维高斯函数分别在水平和垂直方向上继续2次计算。

下面分别贴出Java和dnk2个版本的核心代码。

  • GsUtil.java工具类
/*** @author DaQiang* @time 2020/12/18 14:25* @desc 高斯函数工具类*/
public class GsUtil {public static final float sigma = 1F;public static final int r = 5;/*** 边界处理函数* 之所以引入这个函数,是因为在高斯模糊中,每个点的新值都是由临近的矩形区域的平均值得出,* 但是若矩形区域超出图像范围,则会产生黑边。为了消除这一影响,我们采用对称的方法,* 将矩形的超出部分用内部的对应点代替。** @param x* @param i* @param w* @return*/private static int edge(int x, int i, int w) {// x为中心位置, i为偏移量,w为宽度int inx = x + i;if (inx < 0 || inx >= w)return x - i;return inx;}// 一维高斯函数private static double gaussFunc1D(int x) {double A = 1 / (sigma * Math.sqrt(2 * 3.141592653));double index = -1.0 * (x * x) / (2 * sigma * sigma);return A * Math.exp(index);}// 获取线性的权值空间private static double[] getKernal() {double[] weight = new double[2 * r + 1];double sum = 0;// 获取权值空间weight[]for (int i = 0; i < 2 * r + 1; i++) {weight[i] = gaussFunc1D(i - r);sum += weight[i];}// 归一化for (int i = 0; i < 2 * r + 1; i++) {weight[i] /= sum;}return weight;}//进行两个方向的高斯模糊获// 获取最终的模糊图像public static Bitmap getBlurImage(Bitmap originImg) {int width = originImg.getWidth();int height = originImg.getHeight();// 原图为 originImg// 第一个方向处理的图像为tmpImgBitmap tmpImg = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);// 经过第二次处理的最终结果newImgBitmap newImg = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);double[] weight = getKernal();// 在横向进行一次相加for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {double red = 0, green = 0, blue = 0;for (int i = -r; i <= r; i++) {// 边界处理后的对应的权值矩阵实际值int inx = edge(x, i, width);int color = originImg.getPixel(inx, y);red += Color.red(color) * weight[r + i];green += Color.green(color) * weight[r + i];blue += Color.blue(color) * weight[r + i];}int color = Color.rgb(Integer.parseInt(Math.round(red)+""), Integer.parseInt(Math.round(green)+""), Integer.parseInt(Math.round(blue)+""));int srcColor = originImg.getPixel(x,y);Log.d("GsUtil", "color:" + color+" srcColor: "+srcColor);tmpImg.setPixel(x, y, color);}}// 在纵方向对第一次的结果重新进行一次for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {double red = 0, green = 0, blue = 0;for (int i = -r; i <= r; i++) {int iny = edge(y, i, height);int color = tmpImg.getPixel(x, iny);red += Color.red(color) * weight[r + i];green += Color.green(color) * weight[r + i];blue += Color.blue(color) * weight[r + i];}int color = Color.rgb(Integer.parseInt(Math.round(red)+""), Integer.parseInt(Math.round(green)+""), Integer.parseInt(Math.round(blue)+""));newImg.setPixel(x, y, color);}}return newImg;}}
  • native-lib.cpp
#include <jni.h>
#include <string>
#include<math.h>
#include <android/bitmap.h>
#include <stdlib.h>
#include <android/log.h>#define TAG "native-lib" // 这个是自定义的LOG的标识
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型float sigma = 3;
int r = 9;int edge(int x, int i, int w) {// x为中心位置, i为偏移量,w为宽度int inx = x + i;if (inx < 0 || inx >= w)return x - i;return inx;
}double gaussFunc1D(int x) {double A = 1 / (sigma * sqrt(2 * 3.141592653));double index = -1.0 * (x * x) / (2 * sigma * sigma);return A * exp(index);
}void getKernal(double *weight) {//    double *weight = new double[2 * r + 1];double sum = 0;// 获取权值空间weight[]for (int i = 0; i < 2 * r + 1; i++) {weight[i] = gaussFunc1D(i - r);sum += weight[i];}// 归一化for (int i = 0; i < 2 * r + 1; i++) {weight[i] /= sum;}
}extern "C"
JNIEXPORT jintArray JNICALL
Java_com_example_imagendk_ImageUtil_getImageGaoSiMohu(JNIEnv *env, jclass clazz, jintArray arr,jint width, jint height) {jint *source = (*env).GetIntArrayElements(arr, NULL);int newSize = width * height;double *weight = new double[2 * r + 1];getKernal(weight);int *temp = new int[newSize];int *re = new int[newSize];// 在横向进行一次相加for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {double red = 0, green = 0, blue = 0;for (int i = -r; i <= r; i++) {// 边界处理后的对应的权值矩阵实际值int inx = edge(x, i, width);int color = source[y * width + inx];int tmpRed = (color >> 16) & 0xFF;int g = (color >> 8) & 0xFF;int b = color & 0xFF;red += tmpRed * weight[r + i];green += g * weight[r + i];blue += b * weight[r + i];}int color = 0xff000000 | (int(red) << 16) | (int(green) << 8) | int(blue);temp[y * width + x] = color;}}// 在纵方向对第一次的结果重新进行一次for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {double red = 0, green = 0, blue = 0;for (int i = -r; i <= r; i++) {int iny = edge(y, i, height);int color = temp[iny * width + x];int tmpRed = (color >> 16) & 0xFF;int g = (color >> 8) & 0xFF;int b = color & 0xFF;red += tmpRed * weight[r + i];green += g * weight[r + i];blue += b * weight[r + i];}int color = 0xff000000 | (int(red) << 16) | (int(green) << 8) | int(blue);re[y * width + x] = color;}}jintArray result = (*env).NewIntArray(newSize);(*env).SetIntArrayRegion(result, 0, newSize, re);(*env).ReleaseIntArrayElements(arr, source, 0);(*env).ReleaseIntArrayElements(arr, temp, 0);(*env).ReleaseIntArrayElements(arr, re, 0);return result;
}

Android NDK图片模糊处理之高斯模糊算法相关推荐

  1. android 本地图片模糊,Android端图片模糊的实现原理及方案

    作者:牛栋凯 前言 图片模糊是Android客户端开发中一种比较常见的特效,诸如对话框背景半透明效果,头像背景模糊效果都是通过图片模糊技术实现的.本文主要介绍图片模糊的实现原理及实现方案. 图片模糊原 ...

  2. android怎么处理模糊图片,Android 图片的高斯模糊处理

    一.前言: 我们在开发过程中,经常会遇到高斯模糊的图片,或者高斯模糊背景的情况,所以今天记录一下,下面是效果图: 普通图片.png 高斯模糊图片.png 高斯模糊背景图片.png 二.使用: 1. 依 ...

  3. 基于正态分布的图片高斯模糊算法

    前言: 先来看看下面这张图,我把一张图进行了二等份了,左边是经过高斯模糊过的,右边是原图. 图-1 高斯模糊效果对比图 概述: 高斯模糊也叫做高斯平滑,是一种图像平滑处理的技术.高斯模糊算法的原理是选 ...

  4. Java中beimage_GitHub - beconf/ImageBlurring: Android 中通过 Java 与 JNI 分别进行图片模糊;并且进行比较其运算速度。...

    ImageBlurring Android 中通过 Java 与 JNI 分别进行图片模糊:并且进行比较其运算速度. 相关文章 备注消息 Screenshots RenderScript Fast B ...

  5. android 网络图片工具类,分享一个Android图片模糊的工具类

    图片模糊,试过很多工具什么的,还是这个类比较好,直接用就好了 使用方法: imageView.setImageBitmap(BlurUtil.doBlur(drawable,10,15)); pack ...

  6. android 截图模糊,Adobe XD导出图片模糊?设置错误啦(切图详解)

    Adobe XD CC是一款矢量设计软件,支持导出PNG.SVG.PDF.JPG四种格式,XD中文网(https://xd.94xy.com)的数万用户群和学员中,有非常多的童鞋表示Adobe XD ...

  7. Android 实现图片的高斯模糊(两种方式)

    做项目时遇到要做图片模糊的需求,和微信语音通话的背景效果一样.网上有很多不错的博客,记录一下使用的两种方式. 1. 先来看看第一种,博客原文 首先创建一个工具类 /*** 快速模糊化工具*/ publ ...

  8. android 背景磨砂效果,跨浏览器磨砂效果背景图片模糊特效

    background-blur是一款非常炫酷的跨浏览器磨砂效果背景图片模糊特效jQuery插件.它会抽取图片的主要色彩,并通过SVG过滤器来制作模糊效果.并且它还通过velocity.js来提供额外的 ...

  9. android canvas png 失真,【小程序】--------------处理canvas导出图片模糊问题-------------【劉】...

    一.业务需求: 使用canvas在前端生成海报,并在海报上添加上水印.最后导出图片并保存到本地. 二.业务逻辑实现: (1)创建canvas画布======>(2)在canvas上绘制海报=== ...

最新文章

  1. 单片机定时器精准定时_PIC单片机的定时器精准计时的计算
  2. vba传值调用_Access VBA如何使用Shell命令以及如何传递参数
  3. mybatis 查询的时间不对_程序员,Mybatis 你踩过坑吗?
  4. [css] 写出主流浏览器内核私有属性的css前缀
  5. c#字符型转化为asc_C#字符串和ASCII码的转换
  6. 北方民族大学计算机全国排名,校友会:全国15所民族类大学排名,这三所大学进入十强...
  7. RAC 中 ASM 实例名 与 节点的对应关系
  8. loadrunner之header相关,token等
  9. ITU-T G.1080 IPTV的体验质量(QoE)要求 (Quality of experience requirements for IPTV services)
  10. 合批/批量渲染 (Batch)、实例化Instancing
  11. deepstream多路rtsp流,避免相互影响
  12. navicat 连接oracle的配置
  13. 机器学习:线性模型-多重共线性问题的解决-岭回归
  14. Android逆向-实战so分析-某洲_v3.5.8_unidbg学习
  15. 基于生物特征信息的身份识别(指纹、面部识别的方式和原理)的使用问题的思考
  16. Windows Azure HDInsight 支持预览版 Hadoop 2.2 群集
  17. 销售——LPN(License Plate Number)
  18. Java实现哥德巴赫猜想
  19. Lync 客户端:无法登陆到Lync,验证服务器中的证书时遇到问题
  20. 不要成为反DDoS攻击的局外人

热门文章

  1. 12306抢票客户端(1)账户登录Post表单
  2. C# 带小数点儿的字符串(如:88.6),取整数部分(或四舍五入)
  3. Vue3.0 mixin的使用 以及混合方式讲解
  4. RPG Maker MV/ MZ 工程打包 Android APK 文件(使用 Website 2 APK Builder Pro)
  5. 商用密码算法的实现(常见的密码算法库)
  6. CCNA培训课总结笔记--RIPv1负载均衡(六)
  7. matlab 数值型日期的转换
  8. 一图让您辨别ISO9001\ISO20000\ISO27001认证证书真假的技巧
  9. 通过json配置生成form表单,vue3+ts+elementPlus,form表单组件封
  10. 聚焦虚拟化安全之“无代理防毒”(视频)