OpenCV实战之(1)图片滤镜

前言:之前写过关于android中通过JNI使用NDK的demo,介绍了关于so文件的生成与使用,但仅仅是demo,总觉得脱离实际应用的话相关的东西很快就会忘掉,最近准备面试才发现之前关于Cmake的配置等步骤确实忘的差不多了,这两天刚入职,手头还不忙,于是赶紧找了下OpenCV相关的实际应用来练练手(OpenCV,高级android开发面试必备的)

如果对Cmake涉及的结构和配置不了解建议先花10分钟看看:
1.Cmake方式生成so
2.Cmake方式调用so

国际惯例:开局一张图,实现慢慢侃


image.png

各种滤镜native算法处理参考:https://blog.csdn.net/yangtrees
如图:分别展示的是 原图、灰度处理、高斯模糊、流金岁月、凹雕刻、突浮雕
其他各种效果参考上面链接中的系列文章,找到对应算法稍加修改即可,注意事项下文中会提到。

OpenCV之滤镜效果实现步骤梳理:

1.OpenCV Android资源包下载
下载地址
2.新建android项目,勾选c++支持(旧项目添加c++支持可以手动去新建CMake等文件再修改配置,具体可以参考之前的文章:so生成篇
3.main目录下面新建jniLibs文件夹,将需要适配的cpu类型对应的so文件复制进去(文件在步骤1下载的OpenCV-android-sdk\sdk\native\libs中)
4.将include文件夹复制到cpp下(里面是opencv库的头文件,在你自己的c++代码文件中导入头文件就可以使用opencv的函数了)

image.png

5.(重点)配置CMakeLists,配置so路径和头文件路径,使的在自己的c++文件中可以导入头文件,使用opencv,具体配置如下:

#CMake最低版本3.4.1
cmake_minimum_required(VERSION 3.4.1)
#作用不太清楚
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#配置头文件路径,CMAKE_SOURCE_DIR为 CMakeList同级目录,即app下,通过${CMAKE_SOURCE_DIR}再定位到include
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
#添加opencv动态链接库的引用
add_library(libopencv_java3 SHARED IMPORTED)
#设置opencv动态链接库的引用的路径,${ANDROID_ABI}根据设备cpu型号选文件夹
set_target_properties(
        libopencv_java3
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
#配置通过源码文件testCodeName生成libso-lib.文件  JAVA中  System.loadLibrary("so-lib")去加载这个so
add_library( # Sets the name of the library.
        #这个是声明引用so库的名称,在项目中,如果需要使用这个so文件,引用的名称就是这个。
        #值得注意的是,实际上生成的so文件名称是libso-lib。
        so-lib
        # 这个参数表示共享so库文件,也就是在Run项目或者build项目时会在目录
        SHARED
        #构建so库的源文件
        src/main/cpp/testCodeName.cpp)


#添加log库配置
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)


#将NDK库关联到本地库so-lib   ljnigraphics(高斯模糊算法用到) libopencv_java3(OpenCV)
target_link_libraries( # Specifies the target library.
        so-lib
        ${log-lib}
        -ljnigraphics
        libopencv_java3
        )

6.(重点中的重点)编写c++文件 实现各种滤镜效果算法,函数按JNI命名规则,给JAVA层调用

testCodeName文件中导入的头文件

#include <math.h>
#include <stdlib.h>
#include <jni.h>
//opencv
#include <jni.h>
#include<opencv2/opencv.hpp>
#include<iostream>

这里选取灰度效果来研究
JNI方法中JNIEnv *env, jobject thiz,为固定参数,实际参数为 jintArray buf, jint w, jint h
对应JAVA中的参数就是 int[] 数组,int 宽 int 高,
实际在调用的时候是传入bitmap的像素数组,bitmap宽度,bitmap高,
看看JAVA中的申明:

   //native方法声明
    public native int[] gray(int[] buf, int w, int h);                                         

再看看Activity中的调用(这里直接在Activity中loadLib了,并且Native函数声明gary也在activity中)


image.png

核心代码

       //获取bitmap宽高,新建一个像素数组(此时还没写入像素信息)
       int w = bitmap.getWidth();
        h = bitmap.getHeight();
        int[] pix = new int[w * h];
      

       //灰度处理

        //往pix中写入像素信息
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);  

        //将pix信息和bitmap的宽高  通过Native方法 gray传进去处理像素pix,处理好后返回
        int[] resultPixes = gray(pix, w, h);

        //根据经过灰度处理后的resultPixes像素去创建Bitmap,给Imageview显示
        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
        result.setPixels(resultPixes, 0, w, 0, 0, w, h);
        iv1.setImageBitmap(result);
   

毫无疑问,这里的核心是JNI层中的gray方法,下面重点分析

JNI中函数:

1.

extern "C" JNIEXPORT jintArray JNICALL

Java_com_example_lunwang_ndktest_MainActivity_gray(JNIEnv *env, jobject thiz, jintArray buf, jint w,
                                                   jint h) {

    jint *cbuf;
    jboolean ptfalse = false;
    cbuf = env->GetIntArrayElements(buf, &ptfalse);
    if (cbuf == NULL) {
        return 0;
    }

    Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);    // 注意,Android的Bitmap是ARGB四通道,而不是RGB三通道

这部分代码的作用就是根据传入的Bitmap的像素,宽,高去建立一个 Mat对象
Mat是opencv中的图像对象, Mat对象封装了图像在内存中的信息,用于表示一副加载到内存中的图像,
实际的滤镜效果就是通过opencv提供的函数去处理Mat对象得到的,所以得到如下结论:

1.Mat是opencv处理图片的一个很重要的对象
2.JAVA->JNI->OpenCV处理的转化过程涉及到Bitmap->jintArray->Mat的转化
3.Android的Bitmap是ARGB四通道,而不是RGB三通道,所以这里生成Mat用的是CV_8UC4,网上找的滤
镜效果算法可能用的是CV_8UC3,要注意改过来,对应的算法中如果遇到类似:float R = P0[3* x + 2];的结构注意
改成float R = P0[4 * x + 2];

2.

   cvtColor(imgData, imgData, CV_BGRA2GRAY);
   cvtColor(imgData, imgData, CV_GRAY2BGRA);

//这两行就是调用opencv的方法去处理Mat,其他效果这里的处理会不同

3.

    int size = w * h;
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, (jint *) imgData.data);
    env->ReleaseIntArrayElements(buf, cbuf, 0);
    return result;
}

//这几行就是拿到处理后的Mat,去生成像素数组,返回给JAVA层
//在这个demo中,除了高斯模糊外,几乎所有的滤镜效果的实现1和3不变,就是改变2的处理。

项目demo地址:https://gitee.com/lunguoguo/OpencvProject

这种导入so的方式会造成APK体积巨大,下篇尝试通过其他方式仅仅导入使用到的资源去实现!

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

推荐阅读更多精彩内容

  • 货币通道与银行融通是融通工具的一体两面,货币主导市场经济的融通,银行主导货币载体的融通… 拥有货币是财富的象征,所...
    光瞄芭比阅读 93评论 0 0
  • 【Day29课后实践】周日自习 这是2018年9月2日“崔律·100天精力和时间管理训练营”第4.7讲(自习)的课...
    吖吖_學語阅读 178评论 0 0