美文网首页Android coder进阶andnroidAndroid实践
Android的毛玻璃模糊效果,我使用OpenCV来搞

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

作者: JerryloveEmily | 来源:发表于2017-07-13 22:52 被阅读3157次

    开始学习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进一步的学习使用还会继续记录在博客中。

    相关文章

      网友评论

      • 1aaca13ce0c3:大神能讲讲简单的人脸识别么
      • benzly:可不止这三种方式,而且列举的这种也很麻烦。
        Anwfly: @benzly 哪种的好,共享啊
      • 第一号伤心人:Window的背景呢?比如Activity、Dialog 等
        一发元气弹:@第一号伤心人 setBackgroud....哥们灵活点
        第一号伤心人:@JerryloveEmily 根布局是Layout啊。怎么转换?
        JerryloveEmily:@第一号伤心人 bitmap都拿到了 背景转换下类型几好
      • 凄惨红:我想知道这个库添加后,app体积会增加多少?
        第一号伤心人:Window的背景呢?比如Activity、Dialog 等
        JerryloveEmily:@凄惨红 有点大 8M 这里不是说毛玻璃一定得用opencv的方式,只是提供了一种思路,opencv本身功能是很强大的 这个就是取舍的问题
      • 七岁就狠拽:厉害了:+1:
      • crazyandcoder:能去毛玻璃效果吗?去马赛克
        EasyBookM:你这个需求应该需要付费吧
      • Clendy:佩服~~ 玩OpenCV还是3年前读研时...
      • 王大胆:厉害,厉害,jerry哥
        JerryloveEmily:@王大胆 你倒是来个赞赏啊:grin::grin::grin:
        JerryloveEmily:@王大胆 必须的

      本文标题:Android的毛玻璃模糊效果,我使用OpenCV来搞

      本文链接:https://www.haomeiwen.com/subject/wuyghxtx.html