• 创建OpenCV-Android库

    2017-07-12 12:01:10
    罗总提出OpenCV-Android库中包含了太多安卓开发板不需要的动态库,让我把这些不需要的动态库从OpenCV-Android库中剔除去。参考 steveliles 的opencv-android项目,我对新发布的 opencv-3.2.0-android-sdk.zip 进行了...

    起因

    2016年的最后一周,和西安研发中心的罗总,一起联调了安卓开发板中图像识别的算法。罗总提出OpenCV-Android库中包含了太多安卓开发板不需要的动态库,让我把这些不需要的动态库从OpenCV-Android库中剔除去。

    参考 stevelilesopencv-android项目,我对新发布的 opencv-3.2.0-android-sdk.zip 进行了封装。

    为什么要对OpenCV的安卓库进行封装?

    因为官网提供的 opencv-3.2.0-android-sdk.zip,虽然可以直接导入使用,但是,需要用到相应平台的 apk。也就是说,如果,你要在自己的app中运行opencv的代码,需要先安装相应平台的apk。

    OpenCV_3.2.0_Manager_3.20_arm64-v8a.apk
    OpenCV_3.2.0_Manager_3.20_armeabi-v7a.apk
    OpenCV_3.2.0_Manager_3.20_armeabi.apk
    OpenCV_3.2.0_Manager_3.20_mips.apk
    OpenCV_3.2.0_Manager_3.20_mips64.apk
    OpenCV_3.2.0_Manager_3.20_x86.apk
    OpenCV_3.2.0_Manager_3.20_x86_64.apk

    readme.txt

    How to select the proper version of OpenCV Manager
    --------------------------------------------------
    
    Since version 1.7 several packages of OpenCV Manager are built. Every package is targeted for some
    specific hardware platform and includes corresponding OpenCV binaries. So, in all cases OpenCV
    Manager uses built-in version of OpenCV. The new package selection logic in most cases simplifies
    OpenCV installation on end user devices. In most cases OpenCV Manager may be installed automatically
    from Google Play.
    
    If Google Play is not available (i.e. on emulator, developer board, etc), you can install it
    manually using adb tool:
    
        adb install <path-to-OpenCV-sdk>/apk/OpenCV_<version>_Manager_<app_version>_<platform>.apk
    
    Example: OpenCV_3.2.0-dev_Manager_3.20_armeabi-v7a.apk
    
    Use the list of platforms below to determine proper OpenCV Manager package for your device:
    
    - armeabi (ARMv5, ARMv6)
    - armeabi-v7a (ARMv7-A + NEON)
    - arm64-v8a
    - mips
    - mips64
    - x86
    - x86_64

    创建自己的OpenCV-Android库

    1. 下载 OpenCV for Android

    从OpenCV官网下载OpenCV3.2.0的OpenCV for Android压缩文件opencv-3.2.0-android-sdk.zip

    2. 创建OpenCV4Android项目

    利用Android Studio 2.2.3创建一个android项目,这里我创建的是OpenCV4Android项目。

    3. 创建OpenCV-Android库

    • 依次点击File->New->New Module…,在弹出的对话框中,选择Android Library,然后,点击Next
    • Application/Library name:处,输入安卓库名称OpenCV-Android
      点击Package name:后面的Edit,修改包名称为org.opencv

    4. 配置OpenCV-Android库

    • 解压下载的opencv-3.2.0-android-sdk.zip
    • 复制OpenCV-android-sdk/sdk/java/src/org/opencv文件夹内的所有子文件夹,并粘贴到自己创建的OpenCV-Android库中opencv-android/src/main/java/org/opencv的文件夹下。
    • opencv-android/src/main/java/org/opencv/android子文件中,做如下操作:

      • 删除AsyncServiceHelper.java文件
      • 修改OpenCVLoader.java文件,注释掉以下内容:
      /**
       * Loads and initializes OpenCV library using OpenCV Engine service.
       * @param Version OpenCV library version.
       * @param AppContext application context for connecting to the service.
       * @param Callback object, that implements LoaderCallbackInterface for handling the connection status.
       * @return Returns true if initialization of OpenCV is successful.
       */
      //    public static boolean initAsync(String Version, Context AppContext,
      //            LoaderCallbackInterface Callback)
      //    {
      //        return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback);
      //    }
    • 复制OpenCV-android-sdk/sdk/java/res/values/attrs.xmlopencv-android/src/main/java/res/values/文件内;
    • 修改opencv-android/src/main/java/res/values/string.xml,修改后如下所示:

      <resources>
      <string name="app_name">OpenCV-3.2.0</string>
      </resources>
    • OpenCV-android-sdk/sdk/native/libs文件夹下的子文件夹和OpenCV-android-sdk/sdk/3rdparty/libs文件夹下的子文件夹拷贝opencv-android/src/main文件下创建的jniLibs文件夹内。

    app文件内相关文件修改

    修改app/src/main/res/layout/activity_main.xml

    <TextView>添加id,修改后代码片段如下所示:

        <TextView
            android:id="@+id/text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />

    为app添加opencv-android库

    1. 点击File->Project Structure…打开Project Structure对话框;
    2. 点击Modules下的app,再在右侧点击Dependencies
    3. 点击Dependencies下框附近的+号,选择3 Module Dependency,在弹出的对话框中,选择:opencv-android,最后依次点击OKOK

    修改MainActivity

    添加TextView对象,如果点击该对象,则弹出一个短消息!

    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TextView textView = (TextView) findViewById(R.id.text_view);
            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(MainActivity.this, "You clicked textView!", Toast.LENGTH_SHORT).show();
                    if (OpenCVLoader.initDebug()) {
                        textView.setText("OpenCV320 loaded successful!");
                    }
                }
            });
        }
    }

    运行

    点击Run->Run ‘app’,启动虚拟手机的界面如下所示:

    helloWorld

    点击,Hello World!后的界面如下所示:

    helloCV

    找到opencv-android库对应的aar文件

    opencv-android/build/outputs/aar文件夹下,有生成的debug和release两种格式的aar文件夹。

    opencv-android-debug.aar
    opencv-android-release.aar

    如何导入aar文件

    参考这里

    Bonus

    修改app和opencv-android文件夹内的build.gradle文件中的buildTypes字段,仅生成适合指定平台的apk文件。

        buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
                // added by JohnTian
                splits {
                    abi {
                        enable true
                        reset()
                        include 'armeabi-v7a', 'arm64-v8a'
                        universalApk false
                    }
                }
            }

    Github

    OpenCV4Android

    写在最后

    新的一年,祝福小伙伴们,新年快乐,身体健康,阖家欢乐,工作顺利,事事顺心!

    展开全文
  • 根据自己需要的模块交叉编译 Android OpenCV ,如下面的脚本只编译了 opencv_core 、opencv_imgproc、opencv_video 三个模块,如果需要裁剪自定制,可以修改 build_opencv_modules 函数,打开或关闭你需要的模块。...

    根据自己需要的模块交叉编译 Android OpenCV 库,如下面的脚本只编译了 opencv_core 、opencv_imgproc、opencv_video 三个模块,如果需要裁剪自定制,可以修改 build_opencv_modules 函数,打开或关闭你需要的模块。模块所需要依赖的其他模块可在 OptionArgs.txt 里查找 xxx_LIB_DEPENDS,xxx 为要编译的模块。比如,要编译 opencv_video,可以在 OptionArgs.txt 里搜索 opencv_video_LIB_DEPENDS 可以看到其依赖于 opencv_core 和 opencv_imgproc 模块:

    //Dependencies for the target
    opencv_video_LIB_DEPENDS:STATIC=general;opencv_core;general;opencv_imgproc;general;dl;general;m;general;log;
    

    下面脚本已放在 github

    交叉编译脚本如下(使用时记得将 NDK 改成自己的路径):

    #!/bin/bash
    
    # Author: AlanWang
    # Email: alanwang4523@gmail.com
    # Date: 2020-06-10
    
    
    NDK_PATH="/Users/AlanWang/AndroidDev/android-ndk-r16b"
    CMAKE_TOOLCHAIN_PATH="${NDK_PATH}/build/cmake/android.toolchain.cmake"
    
    echo "build opencv for android"
    
    function build_opencv_modules
    {
        ARCH_ABI=$1
        API_LEVEL=$2
    
        cmake \
        -DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_PATH \
        -DCMAKE_BUILD_TYPE=Release \
        -DANDROID_NDK=$NDK_PATH  \
        -DCMAKE_CXX_FLAGS=-std=c++11 \
        -DANDROID_ABI=$ARCH_ABI \
        -DANDROID_STL=c++_static \
        -DENABLE_CXX11=ON \
        -DBUILD_ANDROID_PROJECTS=OFF \
        -DBUILD_ANDROID_EXAMPLES=OFF \
        -DBUILD_JAVA=OFF  \
        -DBUILD_CUDA_STUBS=OFF \
        -DBUILD_DOCS=OFF \
        -DBUILD_EXAMPLES=OFF \
        -DBUILD_JASPER=OFF \
        -DBUILD_JPEG=OFF \
        -DBUILD_OPENEXR=OFF \
        -DBUILD_PACKAGE=OFF \
        -DBUILD_PERF_TESTS=OFF \
        -DBUILD_PNG=OFF \
        -DBUILD_SHARED_LIBS=OFF \
        -DBUILD_TBB=OFF  \
        -DBUILD_TESTS=OFF \
        -DBUILD_TIFF=OFF  \
        -DBUILD_WITH_DEBUG_INFO=OFF  \
        -DBUILD_WITH_DYNAMIC_IPP=OFF  \
        -DBUILD_ZLIB=OFF  \
        -DBUILD_opencv_apps=OFF \
        -DBUILD_opencv_calib3d=OFF \
        -DBUILD_opencv_core=ON \
        -DBUILD_opencv_features2d=OFF \
        -DBUILD_opencv_flann=OFF \
        -DBUILD_opencv_highgui=OFF \
        -DBUILD_opencv_imgcodecs=OFF \
        -DBUILD_opencv_imgproc=ON \
        -DBUILD_opencv_ml=OFF \
        -DBUILD_opencv_objdetect=OFF \
        -DBUILD_opencv_photo=OFF \
        -DBUILD_opencv_python2=OFF \
        -DBUILD_opencv_python3=OFF \
        -DBUILD_opencv_shape=OFF \
        -DBUILD_opencv_stitching=OFF \
        -DBUILD_opencv_superres=OFF \
        -DBUILD_opencv_ts=OFF \
        -DBUILD_opencv_video=ON \
        -DBUILD_opencv_videoio=OFF \
        -DBUILD_opencv_videostab=OFF \
        -DBUILD_opencv_world=OFF \
        -DWITH_IPP=OFF \
        -DWITH_FFMPEG=OFF \
        -DWITH_CUDA=OFF \
        -DWITH_CUFFT=OFF \
        -DWITH_EIGEN=OFF \
        -DWITH_JASPER=OFF \
        -DWITH_JPEG=OFF \
        -DWITH_PNG=OFF \
        -DWITH_PTHREADS_PF=OFF \
        -DWITH_OPENEXR=OFF \
        -DWITH_MATLAB=OFF \
        -DWITH_TBB=OFF \
        -DWITH_TIFF=OFF \
        -DWITH_WEBP=OFF \
        -DANDROID_NATIVE_API_LEVEL=${API_LEVEL} ../../
    
        make clean
        make -j8
        make install
    }
    
    function mv_dirs {
        rm -rf $2
        mkdir -p $2
        mv $1/* $2/
    }
    
    function build_opencv {
        rm -rf $1
        mkdir $1
        cd $1
    
        build_opencv_modules $1 $2
    
        OPENCV_LIBS_PATH="./install/sdk/native/libs/$1"
        OUTPUT_LIBS_PATH="../opencv/$1"
        mv_dirs ${OPENCV_LIBS_PATH} ${OUTPUT_LIBS_PATH}
    
        OTHER_LIBS_PATH="./install/sdk/native/3rdparty/libs/$1"
        OUTPUT_3RDPARTY_LIBS_PATH="../3rdparty/$1"
        mv_dirs ${OTHER_LIBS_PATH} ${OUTPUT_3RDPARTY_LIBS_PATH}
    
        INCLUDE_PATH="./install/sdk/native/jni/include"
        OUTPUT_INCLUDE_PATH="../opencv/include"
        mv_dirs ${INCLUDE_PATH} ${OUTPUT_INCLUDE_PATH}
    
        cd ..
        rm -rf $1
    
        cur_path=$(pwd)
        echo ${cur_path}
    }
    
    
    rm -rf build_android
    mkdir build_android
    cd build_android
    mkdir opencv
    mkdir 3rdparty
    
    build_opencv armeabi-v7a 16
    build_opencv arm64-v8a 21
    
    

    操作步骤:
    1、将其保存在 build_android.sh 并赋予执行权限
    2、下载 OpenCV 源码并解压(我编译的 opencv-3.1.0 版本,opencv 所有 release 版本
    3、将 build_android.sh 放入解压后的目录(如:opencv-3.1.0)
    4、进入解压目录 opencv-3.1.0,执行 :

    ./build_android.sh
    

    5、生成的编译好的库在 opencv-3.1.0 下的 build_android 目录
    6、使用时在 CMakeList 里添加 opencv 依赖,注意:被依赖的库要在下面,否则编译连接的时候会提示 opencv 的某些函数未定义。

    ${OPENCV_LIB_PATH}/libopencv_video.a
    ${OPENCV_LIB_PATH}/libopencv_imgproc.a
    ${OPENCV_LIB_PATH}/libopencv_core.a
    

    目录结构如下:
    在这里插入图片描述
    在这里插入图片描述

    github 地址:
    https://github.com/alanwang4523/OpenCV_Build4Android

    展开全文
  • OpenCV OpenCV,全称Open Source Computer VisionLibrary,是基于C/C++编写的,是BSD开源许可...OpenCV支持Windows、Linux、Mac OS、iOS与Android操作系统上的应用开发。 OpenCV Android SDK OpenCV Android SDK 是O...

    OpenCV

    OpenCV,全称Open Source Computer VisionLibrary,是基于C/C++编写的,是BSD开源许可的计算机视觉开发框架,其开源协议允许在学术研究与商业应用开发中免费使用它。OpenCV支持Windows、Linux、Mac OS、iOS与Android操作系统上的应用开发。

    OpenCV Android SDK

    OpenCV Android SDK 是OpenCV针对Android平台提供的开发工具包。Android应用开发一般采用Java或者Kotlin语言进行,而OpenCV主要模块采用C、C++语言编制,因此,我们需要通过JNI技术,实现JAVA或者Kotlin调用OpenCV算法模块的目的。

    下载

    SDK概述

    SDK目录结构如下:

    OpenCV-android-sdk
    |_ samples
    |_ sdk
    |    |_ etc
    |    |_ java
    |    |_ libcxx_helper
    |    |_ native
    |          |_ 3rdparty
    |          |_ jni
    |          |_ libs
    |               |_ arm64-v8a
    |               |_ armeabi-v7a
    |               |_ x86
    |               |_ x86_64
    |          |_ staticlibs
    |               |_ arm64-v8a
    |               |_ armeabi-v7a
    |               |_ x86
    |               |_ x86_64
    |
    |_ LICENSE
    |_ README.android
    
    目录 文件
    samples OpenCV运行案例
    sdk OpenCV API以及依赖库
    sdk/etc Haar和LBP级联分类器
    sdk/java OpenCV Java API
    sdk/libcxx_helper bring libc++_shared.so into packages
    sdk/native OpenCV 静态库、动态库以及JNI文件

    英文详细介绍(https://opencv.org/android/)。其实官方的这些介绍并不详细,很多资料随着版本的迭代已过时,意义不大,唯一阅读性高且具有指导意义的应该就是库内的代码与注释了。

    开发环境

    • Android Studio 3.5.3 & Android SDK

    • Android NDK 20.1.5948944

    • CMake 3.10.2

    • OpenCV Android SDK 4.2.0

    Hello OpenCV Android Sample

    • Open Project
    • 选择OpenCV-android-sdk目录下的samples目录
    • 待编译结束后运行face-detection

    Face Detection运行结果

    Hello OpenCV Android SDK

    • New Project
    • Import Module…
    • 选择OpenCV-android-sdk目录下的sdk目录,修改或者不修改module的名称
    • 添加app程序对sdk module的依赖
    • 期间可能会遇到一些问题,可能是NDK版本问题,可能是API LEVEL问题,也可能是build tools的问题,对应的稍作处理即可。

    示例工程

    https://github.com/onlyloveyd/LearningAndroidOpenCV

    展开全文
  • OpenCV android sdk配置OpenCV android NDK开发实例  【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78374708  在Android应用中调用OpenCV进行图像处理的方法有很多种,考虑到...

    OpenCV android sdk配置OpenCV android NDK开发实例

           【尊重原创,转载请注明出处http://blog.csdn.net/guyuealian/article/details/78374708

            在Android应用中调用OpenCV进行图像处理的方法有很多种,考虑到性能问题,本人推荐使用NDK进行开发,毕竟C/C++要比Java性能好的多。博客会给出详细的例子和配置方法,并给出本人Github的Demo代码,亲们只需git clone,并在本地Android Studio Build一下,即可以在本地Android手机上直接运行了。

    Demo Github地址:https://github.com/PanJinquan/OpenCV-Android-Demo(NDK和Java都支持OpenCV开发)

    老铁要是觉得不错,记得给个“Star”哈

          PS :Opencv3.x以后,已经把很多功能模块放在contrib中,要想移植opencv contrib到Android需要自己编译,这个过程还是相当麻烦的。如果你想支持opencv contrib开发,可以下载本人已经编译且移植好的Android Demo:

     OpenCV-Contrib-Android-Demo: https://github.com/PanJinquan/OpenCV-Contrib-Android-Demo(NDK和Java都支持OpenCV contrib开发)

          整个工程代码都给亲们啦,是不是很照顾大家呢?题外话:之前本人在Android Studio和Eclipse配置OpenCV NDK开发时,踩了不知多少坑,网上教程一大堆,偏偏放在本人机器上就是报各种错误,各种无法解析……。好不容易配置好了,后面又来了个大坑:在Java中Bitmap图像与JNI的OpenCV的Mat图像的数据转换时,出现了各种各样问题,如通道顺序问题,颜色失真问题,数据转换问题等等等等等等……。好在,经过一番折腾,终于把问题解决了。
         言归正传,配置前,先保证版本一样:

    • (1)Android Studio 2.3.3 以上
    • (2)android-ndk-r10d 以上,下载地址:https://developer.android.google.cn/ndk/downloads/index.html
    • (3)OpenCV-3.1.0-android-sdk 以上,下载地址:https://opencv.org/releases.html

    PS:与时俱进,目前Github的OpenCV版本已经升级到:opencv-3.4.2-android-sdk,NDK:android-ndk-r14b

    目录

    OpenCV android sdk配置OpenCV android NDK开发实例

     

    一、OpenCV android sdk配置

    1.第一步:

    2.第二步:

    3.第三步:

    4.第四步:CMakeLists.txt配置

     二、OpenCV android的图像数据转换

    第一种:通过JNI的整型数组传递图像数据:

    第二种:通过自定义图像对象传递图像数据:

    第三种:使用OpenCV的Java包实现NDK开发

    三、三种方法相比


    一、OpenCV android sdk配置

    1.第一步:

        新建工程一定要勾选“Include C++ support”,这样新建的Android工程会直接支持NDK开发,避免各种配置问题,如果提示没有NDK,请下载NDK,并在工程“Project Structure”中导入即可:

    2.第二步:

      新建工程勾选了“Include C++ support”,就已经支持NDK开发了(即native-lib),我们需要做的是,根据自己项目需要,增加JNI接口。

    3.第三步:

      将下载的“OpenCV-android-sdk”放在工程的根目录下:

    4.第四步:CMakeLists.txt配置

         类似于Visual Studio的工程配置,我们需要告诉NDK去哪里查找OpenCV的头文件路径和依赖文件,Android Studio现在已经支持Cmake配置了,修改app/CMakeLists.txt如下:

    #设置OpenCV的路径
    set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../OpenCV-android-sdk/sdk/native/jni)
    find_package(OpenCV REQUIRED)
    #包含OpenCV的头文件
    include_directories( ${CMAKE_SOURCE_DIR}/../OpenCV-android-sdk/sdk/native/jni/include)
    

       此外,还需要在target_link_libraries添加${OpenCV_LIBS} 

    target_link_libraries( # Specifies the target library.
                           imagePro-lib
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib}
                           ${OpenCV_LIBS})

        完整的 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)
    
    
    set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../OpenCV-android-sdk/sdk/native/jni)
    find_package(OpenCV REQUIRED)
    include_directories( ${CMAKE_SOURCE_DIR}/../OpenCV-android-sdk/sdk/native/jni/include)
    
    
    # Creates and names a library, sets it as either STATIC
    # or SHARED, and provides the relative paths to its source code.
    # You can define multiple libraries, and CMake builds them for you.
    # Gradle automatically packages shared libraries with your APK.
    #声明库名称、类型、源码文件
    #add_library( # Sets the name of the library.
    #             native-lib
    #
    #            # Sets the library as a shared library.
    #            SHARED
    #
    #            # Provides a relative path to your source file(s).
    #           src/main/cpp/native-lib.cpp)
    
     add_library( # Sets the name of the library.
                  imagePro-lib
    
                  # Sets the library as a shared library.
                  SHARED
    
                  # Provides a relative path to your source file(s).
                  src/main/cpp/imagePro.cpp
                  src/main/cpp/AndroidDebug.cpp
                  )
    
    
    # Searches for a specified prebuilt library and stores the path as a
    # variable. Because CMake includes system libraries in the search path by
    # default, you only need to specify the name of the public NDK library
    # you want to add. CMake verifies that the library exists before
    # completing its build.
    
    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 )
    
    # Specifies libraries CMake should link to your target library. You
    # can link multiple libraries, such as libraries you define in this
    # build script, prebuilt third-party libraries, or system libraries.
    #将NDK库链接到native库中,这样native库才能调用NDK库中的函数
    #target_link_libraries( # Specifies the target library.
    #                       native-lib
    #                       imagePro-lib
    #
    #                       # Links the target library to the log library
    #                       # included in the NDK.
    #                       ${log-lib} )
    
    target_link_libraries( # Specifies the target library.
                           imagePro-lib
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib}
                           ${OpenCV_LIBS})
    
    
    #include_directories() - 指定关联的头文件目录

       clean一下,并重新编译,这样NDK就支持OpenCV开发了。

     PS:到这里,只是表示NDK C++层可以支持OpenCV开发了,要是想在Java层中,直接使用OpenCV的Java包,还需要导入“OpenCV-android-sdk”的Java,方法是可以参考:http://blog.csdn.net/u010097644/article/details/56849758

     二、OpenCV android的图像数据转换

       Android开发中,图像类型一般是Bitmap,而在OpenCV是Mat,两者数据的转换需要进行特殊的处理。本OpenCVDemo实现了三种方法,可以现实Android的Bitmap图像与OpenCV的Mat类型的互转。

    第一种:通过JNI的整型数组传递图像数据:

    (1)定义JNI接口

        public native int[] ImageBlur(int[] pixels,int w,int h);

    说明:

    pixels:整型数组,存储图像的像素值;

     w:图像的宽度;

     h:图像的高度;

     返回整型数组,处理后的图像像素值;

          Android的Bitmap图像需要利用getPixels方法,将Bitmap转为整型数组pixels。再调用ImageBlur接口进行OpenCV的图像处理,处理完后,返回的图像数据需要用setPixels转为Bitmap图像进行显示。问题来了:Bitmap.Config有多个属性,用哪个呢?

    public static final Bitmap.Config  ARGB_4444 //4个4位组成即16位
    public static final Bitmap.Config  ARGB_8888//4个8位组成即32位
    public static final Bitmap.Config  RGB_565//R为5位,G为6位,B为5位共16位

         一开始,脑残,直接选了RGB_565,心思细腻测试部门的妹子,发现一个巨坑Bug:原图与OpenCV接收的图像总是有细微的差异,即出现了失真问题。后来,调试发现,就是RGB_565导致转换到CV_8UC3出现数据丢失的情况。不难得出,应该用ARGB_8888类型,毕竟OpenCV中,常用的类型是8位无符号类型:CV_8UC4、CV_8UC3等。

       /**
         * 调用JNI的ImageBlur(int[] pixels,int w,int h)接口实现图像模糊
         */
        public Bitmap doImageBlur(Bitmap origImage) {
            int w = origImage.getWidth();
            int h = origImage.getHeight();
            int[] pixels = new int[w * h];
            origImage.getPixels(pixels, 0, w, 0, 0, w, h);
            int[] image=ImageBlur(pixels,w,h);//JNI
            Log.i(TAG, "ImageBlur called successfully");
            //最后将返回的int数组转为bitmap类型。
            Bitmap desImage=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
            //faceall为返回的int数组
            desImage.setPixels(image,0,w,0,0,w,h);
            return desImage;
        }

    (2)JNI数据封装:
        需要注意的是,上层Java传递进来的图像数据是四通道的,即ARGB,而在OpenCV图像处理中,我们往往希望处理的图像数据是BGR三通道的。特别需要注意的是,OpenCV处理图像数据的通道顺序是B、G、R,而不是R、G、B,不然很容易出现图像变色的问题。 

    extern "C"
    JNIEXPORT jintArray  JNICALL Java_com_panjq_opencv_alg_ImagePro_ImageBlur
            (JNIEnv *env, jobject obj, jintArray buf, jint w , jint h){
       LOGD("ImageBlur: called JNI start...");
        //读取int数组并转为Mat类型
        jint *cbuf = env->GetIntArrayElements(buf,JNI_FALSE);
        if (NULL == cbuf)
        {
            return 0;
        }
        Mat imgData(h,w,CV_8UC4,(unsigned char*) cbuf);
        cv::cvtColor(imgData,imgData,CV_BGRA2BGR);
        //这里进行图像相关操作
        blur(imgData,imgData,Size(20,20));
    
    
        //对图像相关操作完毕
        cv::cvtColor(imgData,imgData,CV_BGR2BGRA);
        //这里传回int数组。
        uchar *ptr = imgData.data;
        //int size = imgData.rows * imgData.cols;
        int size = w * h;
        jintArray result = env->NewIntArray(size);
    //    env->SetIntArrayRegion(result, 0, size, cbuf);
        env->SetIntArrayRegion(result, 0, size, (const jint *) ptr);
        env->ReleaseIntArrayElements(buf, cbuf, 0);
        LOGD("ImageBlur: called JNI end...");
        return result;
    }

    第二种:通过自定义图像对象传递图像数据:

          JNI接口参数除了可以传递基本数据类型,如:int、 float 、char等基本类型,实质上还可以是引用类型,如:类、实例、数组。第一种方法中,传递的数组就是引用类型(不管是对象数组还是基本类型数组,都作为reference types存在)。详见:http://blog.csdn.net/qinjuning/article/details/7599796
          既然可以传递对象,为什么不直接传递一个图像对象,每次都要传递图像的宽度w和高度h,这不是很麻烦么。OK,we do...!
    (1)定义JNI接口; 

        public native ImageData ImageProJNI(ImageData image_data);

    说明: ImageData是本人定义好的图像数据类,并提供了构造方法,getBitmap和getImageData方法方便数据之间的转换:

    package com.panjq.opencv.alg;
    
    import android.graphics.Bitmap;
    
    /**
     * Created by panjq1 on 2017/10/23.
     */
    
    public class ImageData {
       // public Bitmap bitmap;
        public int[] pixels;
        public int w;
        public int h;
    
        ImageData(){
        }
    
        ImageData(Bitmap bitmap){
            this.w = bitmap.getWidth();
            this.h = bitmap.getHeight();
            //将bitmap类型转为int数组
            this.pixels = new int[this.w * this.h];
            bitmap.getPixels(this.pixels, 0, this.w, 0, 0, this.w, this.h);
        }
    
        public  Bitmap getBitmap( ){
            //int数组转为bitmap类型。
            Bitmap desImage=Bitmap.createBitmap(this.w,this.h,Bitmap.Config.ARGB_8888);
            desImage.setPixels(this.pixels,0,this.w,0,0,this.w,this.h);
            return desImage;
        }
    
        public  ImageData  getImageData(Bitmap bitmap){
            this.w = bitmap.getWidth();
            this.h = bitmap.getHeight();
            this.pixels = new int[w * h];
            bitmap.getPixels( this.pixels, 0, w, 0, 0, w, h);
            return this;
        }
    }
    

           有了这个类和方法,Android的Bitmap图像与OpenCV的Mat数据,就可以很方便地进行数据的转换啦,接口调用方法如下:

      /**
         * 调用JNI的ImageProJNI(ImageData image_data)接口实现图像模糊
         */
        public Bitmap ImageProcess(Bitmap origImage) {
           ImageData imageData=new ImageData(origImage);//创建图像数据imageData对象
    //        ImageData imageData=new ImageData();
    //        imageData.getImageData(origImage);
            Log.i(TAG, "input image size:"+imageData.w+","+imageData.h);
            ImageData out_image=ImageProJNI(imageData);//直接传入图像数据imageData对象
            Log.i(TAG, "return image size:"+out_image.w+","+out_image.h);
            Bitmap desImage=out_image.getBitmap();
            Log.i(TAG, "ImageProJNI called successfully");
            return desImage;
        }
    

            有了这个类和方法,Android的Bitmap图像与OpenCV的Mat数据,就可以很方便地进行数据的转换啦,接口调用方法如下:
    相比第一种方法,第二种方法仅需传入ImageData对象即可,是不是简单明了很多了啦。


    (2)JNI数据封装:
       OK,Java层面简单了,但JNI接口封装就麻烦了,毕竟现在传入的参数是对象,类似与Java的反射机制,在JNI中同样可以获取
       Java类的属性和方法。方法如下:

    extern "C"
    JNIEXPORT jobject JNICALL Java_com_panjq_opencv_alg_ImagePro_ImageProJNI
            (JNIEnv *env, jobject obj, jobject image_obj){
        //获取Java中的实例类
        // jclass jcInfo = env->FindClass("com/panjq/opencv/alg/ImageData");
        jclass jcInfo = env->GetObjectClass(image_obj);
    
        //获得类属性
        jfieldID jf_w = env->GetFieldID(jcInfo, "w", "I");//ImageData类中属性w
        int w = env->GetIntField(image_obj, jf_w);
        jfieldID jf_h = env->GetFieldID(jcInfo, "h", "I");//ImageData类中属性h
        int h = env->GetIntField(image_obj, jf_h);
    
        //ImageData类中属性pixels
        jfieldID jf_pixels = env->GetFieldID(jcInfo, "pixels", "[I");
        //获得对象的pixels数据,并保存在pixels数组中
        jintArray pixels = (jintArray)env->GetObjectField(image_obj, jf_pixels);
        jint *ptr_pixels = env->GetIntArrayElements(pixels, 0);//获得pixels数组的首地址
        Mat imgData(h,w,CV_8UC4,(unsigned char*) ptr_pixels);
        cv::cvtColor(imgData,imgData,CV_BGRA2BGR);
        LOGE("ImageProJNI: input image size=[%d,%d]",imgData.cols,imgData.rows);
        //释放内存空间
        env->ReleaseIntArrayElements(pixels, ptr_pixels, 0);
        //imwrite("/storage/emulated/0/OpencvDemo/input_imgData.jpg",imgData);
        //****************** here to Opencv image relevant processing*****************
        /**
         *
         * 进行OpenCV的图像处理....
         *
         */
        blur(imgData,imgData,Size(20,20));//图像模糊
        resize(imgData,imgData,Size(imgData.cols/4,imgData.rows/4),INTER_LINEAR);//图像缩小4倍
        /**
         *
         *
         */
        //*********************************** end ************************************
        jobject obj_result = env->AllocObject(jcInfo);
        cv::cvtColor(imgData,imgData,CV_BGR2BGRA);
        //imwrite("/storage/emulated/0/OpencvDemo/out_imgData.jpg",imgData);
        uchar *ptr = imgData.data;
        int size = imgData.rows* imgData.cols;
        jintArray resultPixel = env->NewIntArray(size);
        jint *ptr_resultPixel = env->GetIntArrayElements(resultPixel, 0);//获得数组的首地址
        env->SetIntArrayRegion(resultPixel, 0, size, (const jint *) ptr);
        env->SetObjectField(obj_result, jf_pixels, resultPixel);
        h=imgData.rows;
        w=imgData.cols;
        LOGE("ImageProJNI: ouput image size=[%d,%d]",w,h);
        env->SetIntField(obj_result, jf_w, w);
        env->SetIntField(obj_result, jf_h, h);
        env->ReleaseIntArrayElements(resultPixel, ptr_resultPixel, 0);
        return  obj_result;
    }

    第三种:使用OpenCV的Java包实现NDK开发

          首先需要给项目添加OpenCV的java依赖模块,可参考:http://blog.csdn.net/u010097644/article/details/56849758 配置过程。利用bitmapToMat将BitMap图像转为Java OpenCV的Mat图像,再利用Mat的getNativeObjAddr()方法获得图像的Native对象地址,利用Native的对象地址,从而实现C++和Java层的图像数据传递。
    (1)定义JNI接口

    public native void jniImagePro3(long matAddrSrcImage, long matAddrDestImage);

       Java层实现过程:

    public Bitmap ImageProcess3(Bitmap origImage) {
            Log.i(TAG, "called JNI:jniImagePro3 ");
            int w=origImage.getWidth();
            int h=origImage.getHeight();
            Mat origMat = new Mat();
            Mat destMat = new Mat();
            Utils.bitmapToMat(origImage, origMat);//Bitmap转OpenCV的Mat
            jniImagePro3(origMat.getNativeObjAddr(), destMat.getNativeObjAddr());
            Bitmap bitImage = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(destMat, bitImage);//OpenCV的Mat转Bitmap显示
            Log.i(TAG, "jniImagePro3 called successfully");
            return bitImage;
        }

    (2)JNI数据封装:
       利用OpenCV的Native对象地址作为参数传递,其JNI封装过程就十分简单了。 

    extern "C"
    JNIEXPORT void JNICALL Java_com_panjq_opencv_alg_ImagePro_jniImagePro3
            (JNIEnv *, jobject, jlong matAddrSrcImage, jlong matAddrDestImage){
        Mat& srcImage  = *(Mat*)matAddrSrcImage;
        Mat& destImage = *(Mat*)matAddrDestImage;
        cv::cvtColor(srcImage,srcImage,CV_BGRA2BGR);
        blur(srcImage,destImage,Size(20,20));
        cv::cvtColor(destImage,destImage,CV_BGR2BGRA);
    }

        与第二种方法相比,第三种方法借助OpenCV android SDK的方法,其JNI封装过程就简单很多了。

    三、三种方法相比

       (1)性能比较:就运行时间,耗时长久而言:第一种>第二种≈第三种,即第一种最耗时,性能最差,第二种和第三种差不多,不过第三种还是稍微快一点,但相差不大,毕竟是人家官方推荐使用的。
       (2)兼容性:第三种方法需要依赖OpenCV的jar包,而第一种和第二种方法只需要OpenCV的jni就可以,不需要上层Java对OpenCV的支持。因此兼容性好。
       (3)扩展性:显然,第二种方法,通过自定义图像对象传递图像数据的方法,可以在不改变接口参数的情况下,非常方便的新增属性变量,或者删除。

    运行处理效果:

     

    如果你觉得该帖子帮到你,还望贵人多多支持,鄙人会再接再厉,继续努力的~

    展开全文
  • OpenCV4Android开发实录(1):移植OpenCV3.3.0Android Studio 转载请声明出处:http://blog.csdn.net/andrexpert/article/details/78993533   OpenCV4Android系列: 1. OpenCV4Android开发实录(1):移植...

    OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio

    转载请声明出处:http://blog.csdn.net/andrexpert/article/details/78993533

     

    OpenCV4Android系列

    1. OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio

    2.OpenCV4Android开发实录(2): 使用OpenCV3.3.0库实现人脸检测

     

    1.OpenCV开源框架简介
        OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。截止本文日期,OpenCV官方提供的最新版本为OpenCV3.4.0,但是这里将以OpenCV3.3.0为主,根据不同的平台下载方式如下:

       

    (1)  OpenCV核心框架

    (2) OpenCV SDK介绍

    2. 移植OpenCV库到Android Studio

    以静态加载方式
    (1) 创建新的Android Studio工程,将OpenCV库以Module的形式引入到工程中,即File->Import Module,Source directory选中...\opencv-3.3.0-android-sdk\OpenCV-android-
    sdk\sdk\java目录,然后直接下一步即可。

    (2) 添加openCVLibrary330库作为app module的依赖
    步骤:File->Project Structure->选中app的Dependencies选项,点击”+”选中Module dependencies
     
    (3) 配置NDK环境。由于在后面演示使用官方Sample需要使用NDK编译,这里需要在Android Studio工程中配置好NDK环境。
    步骤:File->Project Structure->选中SDK Location选项,设置Android NDK location路径
     
    (4)修改app模块中的build.gradle,添加sourceSets字段。

    android {
        compileSdkVersion 25
        defaultConfig {
            applicationId "com.jiangdg.opencv4android"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
        }
        ….// 代码省略
        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    }

    将工程切换到Android选项,就会看到在app目录下自动生成一个jniLibs目录,然后,我们再将OpenCV本地库(…\opencv-3.3.0-android-sdk\OpenCV-android-sdk\sdk\native\libs)拷贝到工程的jniLibs目录。这里我根据项目所需只拷贝了arm64-v8a、armeabi、armeabi-v7a架构文件,内容如下:
     
    至此,OpenCV库的移植就完成了,整个工程视图如下:

    3.编写第一个OpenCV实例:Hello OpenCV
        HelloOpenCV实例功能比较简单,即通过OpenCV库实现Camera渲染到手机屏幕,以便验证OpenCV库移植到Android Studio是否成功。核心代码如下:
    (1) HelloOpenCVActivity.class

    /**
     * 第一个OpenCV例子
     * Created by jiangdongguo on 2017/12/29.
     */
    public class HelloOpenCVActivity extends AppCompatActivity {
        private static final String TAG = "HelloOpenCVActivity";
        @BindView(R.id.HelloOpenCvView)
        CameraBridgeViewBase mOpenCvCameraView;
        private LoaderCallbackInterface mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    // OpenCV引擎初始化加载成功
                    case LoaderCallbackInterface.SUCCESS:
                        Log.i(TAG, "OpenCV loaded successfully.");
                        // 连接到Camera
                        mOpenCvCameraView.enableView();
                        break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }
            }
        };
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 全屏显示
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
    
            setContentView(R.layout.activity_hello);
            // 绑定View
            ButterKnife.bind(this);
            mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
            // 注册Camera连接状态事件监听器
            mOpenCvCameraView.setCvCameraViewListener(new CameraBridgeViewBase.CvCameraViewListener2() {
    
    
                @Override
                public void onCameraViewStarted(int width, int height) {
                }
    
                @Override
                public void onCameraViewStopped() {
                }
    
                @Override
                public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
                    return inputFrame.rgba();
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            // OpenCVLoader.initDebug()静态加载OpenCV库
    	    // OpenCVLoader.initAsync()为动态加载OpenCV库,即需要安装OpenCV Manager
            if (!OpenCVLoader.initDebug()) {
                Log.w(TAG, "static loading library fail,Using Manager for initialization");
                OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_3_0, this, mLoaderCallback);
            } else {
                Log.w(TAG, "OpenCV library found inside package. Using it!");
                mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    }

    (2) activity_hello.xml

     

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:opencv="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <org.opencv.android.JavaCameraView
            android:id="@+id/HelloOpenCvView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="gone"
            opencv:camera_id="any"
            opencv:show_fps="true" />
    </LinearLayout>

    注:通过JavaCameraView源码可知,JavaCameraView实际上是SurfaceView的一个子类,自定义属性opencv:camera_id为指定摄像头ID,其默认为开启后置摄像头;opencv:show_fps为是否显示帧率。
    (3) AndroidMainfest.xml:添加使用权限

     

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>


    参考资料:
    (1)  OpenCV4Android官网
    (2) OpenCV Tutorials
    (3) Android Development with OpenCV

     

    (4) OpenCV4Android SDK

     

     

    源码下载:https://github.com/jiangdongguo/OpenCV4Android(欢迎star & fork)

     

     

    展开全文
  • OpenCV源码编译android库 之前的文章中介绍过如何源码编译OpenCV库,但是当时编译的是pc的cpu版本,但是在使用中,很多代码最终要运行在手机等便携式设备上,所以本文介绍一下,如何使用OpenCV源码检查编译构建...
  • OpenCVAndroidSDK 并不是纯java语言的计算机视觉,而是基于OpenCV c++ 本地代码、通过java语言接口定义、基于JNI技术实现调用c++本地方法的SDK开发包。 SDK目录下面包含的文件目录 etc目录里面有两个文件夹,里面...
  • win10下cmake编译opencv库问题 1.未配置Android NDK工具链目录 CMake Error at platforms/android/android.toolchain.cmake:451 (message):Could not find neither Android NDK nor Android standalone toolchain. ...
  • OpenCV是著名的跨平台计算机视觉开源,广泛应用于计算机视觉相关领域。OpenCV 已经发布 Android 平台下的 SDK,可以直接导入 Android Studio。OpenCV Android SDK 下载地址: Download OpenCV Android SDK 。...
  • Android平台编译支持OpenCL的Opencv静态
  • 目前基于OpenCV 图像处理的开发都是Windows或LInux下直接C++算法实现,如何将已有的C++实现用在Android上,这就需要用到交叉编译了。本节主要对CMake V3.10 官网教程 Cross Compiling for Android 的简单翻译以及...
  • 现在做的项目需要用到使用摄像头进行颜色识别,也就是牵扯到图像处理的部分,于是便选用了OpenCV这个计算机视觉,这样用的时候直接调用这个库里给你封装好的函数就可以了。 本系列文章参考了《OpenCV Android 开发...
  • opencv android java端开发demodemo: http://download.csdn.net/detail/keen_zuxwang/9847391 Canny Sobel Hist Camera的...使用的OpenCV4Android库OpenCV-2.4.9-android-sdkAndroidManifest.xml(添加camera权限):
  • opencv交叉编译android库

    2020-04-30 17:34:43
    下载android-sdk android-sdk 解压 tools 执行 ./android update sdk 选择一个build-tools安装 android-ndk https://developer.android.google.cn/ndk/downloads 编译 cmake … -DCMAKE_TOOLCHAIN_FILE=…/...
  • 最近完成了Android上使用OpenCV进行图像拼接的功能,通过导入OpenCV的.so或.a,JNI封装C++代码供Java层调用,同时在CMakeLists中指定自己需要的.a以减少的大小,毕竟我只用了拼接功能,其它诸如dnn、video等...
  • 编译使用opencv库android程序上一篇介绍了交叉编译opencv为适合android使用的,现在需要编写测试程序,使用opencv进行处理。由于对cmake还不熟悉,直接使用mk文件来编写(其实mk文件也不是很熟。~.~)关于...
  • 环境: ...3.opencv-3.4.2-android-sdk.zip 下载地址: https://sourceforge.net/projects/opencvlibrary/files/opencv-android/ 1.新建android项目 注意:选择Include C++ support ...
  • 官网上下载最新的OpenCV sdk for android并解压该zip文件 2.将Opencv导入Android Studio,从文件 - >新建 - >导入模块,在解压缩的opencv存档中选择sdk/java文件夹 3.在导入的opencv模块下跟新build....
  • 添加AndroidOpenCV依赖(Android Dependencies) 问题本文地址: http://blog.csdn.net/caroline_wendy如果想要添加OpenCV的依赖, 则需要把OpenCV的"D:\OpenCV-2.4.9-android-sdk\sdk\java"文件夹复制...
  • OpenCV (Open Source Computer Vision Library) is released under a BSD license and hence it's free for both academic and commercial use. It has C++, Python
1 2 3 4 5 ... 20
收藏数 8,723
精华内容 3,489
热门标签