Android的毛玻璃模糊效果,我使用OpenCV来搞

开始学习OpenCV,毛玻璃模糊效果目前网上流行的有三种办法:

  1. 使用java来编写一长串的像素处理办法算法来改变bitmap(性能教差,而且一堆算法代码,难理解,不优雅)
  2. 使用C语言的方式同样使用和java一样的算法来实现(性能好,同样一堆算法代码难理解,也不优雅)
  3. 使用RenderScript这个有Api版本的限制。

现在我们可以利用OpenCV框架中滤波算法来实现图片的模糊虚化。


准备工作:

先到OpenCV官网, 下载Android平台的sdk包: http://www.opencv.org

解压后:
sdk目录里是openCV的一些动态库,cmake构建文件,以及java的一些api。


image.png

新建一个支持NDK的工程:

勾选c++的支持.png
选择stdC++11的标准.png

配置集成OpenCV库到工程:

我这里只编译支持了armeabi,cpu架构的平台,需要在app,module的build.gradle中做一些修改:

image.png

对了这里我使用AS自带的cmake工具来构建NDK库的链接和编译的支持,所以不需要再写Android.mk的配置文件,这里配置下CMakeLists.txt就可以,更加简单:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# 添加我们自己要编译的so库,以及源码文件
add_library(
             image_process
             SHARED
             src/main/cpp/image_process.cpp )

# 增加opencv库
add_library( opencv_java3 SHARED IMPORTED )
# 编译的平台是armeabi
if(${ANDROID_ABI} STREQUAL "armeabi")
# 设置动态库文件的路径属性
set_target_properties(
    opencv_java3
    PROPERTIES IMPORTED_LOCATION
    ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libopencv_java3.so
    )
endif(${ANDROID_ABI} STREQUAL "armeabi")
# opencv库的头文件路径设置,在此是opencv-sdk的路径,当然你也可以把include目录拷贝到工程中
include_directories(
    D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include
)


find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# 需要链接的库
target_link_libraries( # Specifies the target library.
                       image_process
                       opencv_java3
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

上面的添加依赖库,和自己要编译的so库的写法都是差不多的,就是这些套路。(自古深情留不住,总是套路得人心)
同时把sdk中libopencv_java3.so文件拷贝到对应的工程目录下我这里是jniLibs为了方便不然还得配置gradle修改source目录的映射路径:

image.png
image.png

编写java层的对外开发调用api

public class ImageProcessUtils {

    /**
     * 毛玻璃一张图片
     * @param srcBitmap    原始图片
     * @return  毛玻璃后的图片
     */
    public static Bitmap blur(Bitmap srcBitmap){
        // 获取原始图片的宽高
        int width = srcBitmap.getWidth();
        int height = srcBitmap.getHeight();
        // 初始化一个用来存储图片所有像素的int数组
        int[] pixels = new int[width * height];
        // 把原始图片的所有原始存入数组中
        srcBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        // 通过jni本地方法毛玻璃化图片
        blurImage(pixels, width, height);
        // 创建一个新的图片
        Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        // 把处理后的图片像素设置给新图片
        newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return newBitmap;
    }

    // 毛玻璃图片
    public static native void blurImage(int[] pixels, int w, int h);

    // 加载so库
    static {
        System.loadLibrary("image_process");
        System.loadLibrary("opencv_java3");
    }
}

接下来是在NDK中使用opencv来实现图片的毛玻璃化

#include <jni.h>
#include <android/log.h>
#include <opencv2/opencv.hpp>    // 引入opencv库头文件
#include <opencv2/highgui/highgui.hpp> // 引入opencv图形界面,暂时没用到

// 定义了log日志宏函数,方便打印日志在logcat中查看调试
#define TAG "Jerry-NDK-Image-Pro"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)

using namespace cv;

extern "C"
JNIEXPORT void JNICALL
Java_com_jerry_jerryopencvdemo_imageprocess_ImageProcessUtils_blurImage(
        JNIEnv *env,
        jclass jcls,
        jintArray jarr_pixels, 
        jint j_width, 
        jint j_height) {

    // 获取java中传入的像素数组值,jintArray转化成jint指针数组
    jint *c_pixels = env->GetIntArrayElements(jarr_pixels, JNI_FALSE);
    if(c_pixels == NULL){
        return;
    }

    LOGE("图片宽度:%d, 高度:%d", j_width, j_height);

    // 把c的图片数据转化成opencv的图片数据
    // 使用Mat创建图片
    Mat mat_image_src(j_height, j_width, CV_8UC4, (unsigned char*) c_pixels);
    // 选择和截取一段行范围的图片 
    Mat temp = mat_image_src.rowRange(j_height / 3, 2 * j_height / 3);
    // 方框滤波
//    boxFilter(temp, temp, -1, Size(85, 85));
    // 均值滤波
    blur(temp, temp, Size(85, 85));
    // 使用高斯模糊滤波
//    GaussianBlur(temp, temp, Size(45, 13), 0, 0);
    // 将opencv图片转化成c图片数据,RGBA转化成灰度图4通道颜色数据
    cvtColor(temp, temp, CV_RGBA2GRAY, 4);

    // 更新java图片数组和释放c++中图片数组的值
    env->ReleaseIntArrayElements(jarr_pixels, c_pixels, JNI_FALSE);
}

看看效果图对比图:

原图.png
毛玻璃后效果图.png

简单的利用了滤波算法函数处理,来达到毛玻璃的效果,当然opencv的强大远远不限于此。关于opencv进一步的学习使用还会继续记录在博客中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容