Android 接入 OpenCV庫的三種方式

       OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,能夠運行在Linux、Windows、Android和Mac OS操做系統上。它輕量級並且高效——由一系列 C 函數和少許 C++ 類 構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了 圖像處理和計算機視覺方面的不少通用算法。
 
       咱們利用它來作一些圖片的處理,能大大的優化內存的處理。下面我來講說接下OpenCV 的三種方式:
 
1、接入OpenCV 的Java SDK 包,這樣你能夠直接在Java調用OpenCV 的大部分方法。第一種方式適用於對Opencv c++ 不熟悉的童鞋,不須要直接調用C++方案, 由於SDK 已經用JNI 所有封裝好了。假設你已經安裝好JDK、AndroidStudio與NDK環境。
         先到官網 http://opencv.org/releases.html ,下載Android 包,如:opencv-3.2.0-android-sdk.zip。
 
sdk 目錄提供了Android的API與Java 庫
sdk/java 目錄包含了一個 Eclipse 項目,該項目提供 OpenCV 的Java API,且能夠導入到開發環境裏。
sdk/native 目錄包含了OpenCV C++ 頭文件(用於JNI),與Android的 .so動態庫 .a靜態庫。
sdk/etc 目錄包含了Haar 與 LBP cascades 級聯。
apk  目錄包含了用戶安裝在指定的Android設備的安裝文件,該文件使opencv 庫能夠管理opencv API
 
首先: File > New > New Module
 
而後:選擇Import Eclipse ADT Project
 
把sdk/java 下的項目導入到項目裏,而後把這個modules 添加到 app modules裏,
直接在 app 目錄下build.gradle 文件裏dependencies 大括號下添加:
compile project(':openCVLibrary')
 
接着在 app/src/main 目錄下 建立一個jniLibs 目錄,而後把sdk/native/libs 下全部文件 拷貝到jniLibs下,編譯,運行。
 
若是導入後,出現一些android 自帶的類識別不了,那就是由於編譯的SDK版本出錯了。
打開 剛導入 的模塊下 build.gradle 文件,把 compileSdkVersion 與 targetSdkVersion修改爲你最新的SDK版本,如:
 
apply plugin: 'com.android.library'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}
運行,則成功了,我發現彷佛不須要再安裝額外的 opencv 的apk 了。
下面連接是我添加成功的例子: 
https://github.com/xiaoxiaoqingyi/NDKDemos     OpenCV_java 項目
 
2、使用opencv sdk 提供的 C++ 頭文件與 .so動態庫 與 .a靜態庫,本身封裝jni,這樣使用的效率會比第一種方法高一些, 且能夠100%使用opencv 的接口。下面看一下安裝的方式:
 
      用AndroidStudio 建立一個項目,而後在 Java 類裏建立一個native 方法,
再在app/src/main 下建立 jni,而後建立 cpp 文件對於 native 方法。
以上是一個簡單的jni 方法,你能夠查看我之前的 文章: http://www.cnblogs.com/xiaoxiaoqingyi/p/6524165.html
在基本的jni 跑通下,咱們把 opencv 庫加入項目裏,首先:
 
一、把 sdk/native 目錄 拷貝到 項目的 jni 目錄下,
 
而後就是配置 Android.mk文件:
LOCAL_PATH:=$(call my-dir)

include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES := on
OpenCV_CAMERA_MODULES := off
OPENCV_LIB_TYPE :=STATIC

ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include $(LOCAL_PATH)/native/jni/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := OpenCV
LOCAL_SRC_FILES := com_magicing_eigenndk_NDKUtils.cpp
LOCAL_LDLIBS +=  -lm -llog
include $(BUILD_SHARED_LIBRARY)

 

接着配置 Application.mk 文件:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_PLATFORM := android-9
 
最後在 cpp 文件調用 opencv 的方法, 首先導入 #include <opencv2/opencv.hpp> 如:
#include <jni.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>

using namespace cv;

extern "C"

  JNIEXPORT jintArray JNICALL Java_com_magicing_eigenndk_NDKUtils_gray(
          JNIEnv *env, jclass obj, jintArray buf, int w, int h) {

      jint *cbuf;
      cbuf = env->GetIntArrayElements(buf, JNI_FALSE );
      if (cbuf == NULL) {
          return 0;
      }

      Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);

      uchar* ptr = imgData.ptr(0);
      for(int i = 0; i < w*h; i ++){
          //計算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B
          //對於一個int四字節,其彩色值存儲方式爲:BGRA
          int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
          ptr[4*i+1] = grayScale;
          ptr[4*i+2] = grayScale;
          ptr[4*i+0] = grayScale;
      }

      int size = w * h;
      jintArray result = env->NewIntArray(size);
      env->SetIntArrayRegion(result, 0, size, cbuf);
      env->ReleaseIntArrayElements(buf, cbuf, 0);
      return result;
  }
 
而後在 activity 頁面裏顯示處理過的圖片,以下:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        NDKUtils ndk = new NDKUtils();

        Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(
                R.mipmap.pic_test)).getBitmap();
        int w = bitmap.getWidth(), h = bitmap.getHeight();
        int[] pix = new int[w * h];
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);
        int [] resultPixes=ndk.gray(pix,w,h);
        Bitmap result = Bitmap.createBitmap(w,h, Bitmap.Config.RGB_565);
        result.setPixels(resultPixes, 0, w, 0, 0,w, h);

        ImageView img = (ImageView)findViewById(R.id.img2);
        img.setImageBitmap(result);

    }

}

運行成功後:html

 

我編譯成功的項目連接:
https://github.com/xiaoxiaoqingyi/NDKDemos   (OpenCV_native項目)
官網參考資料:
 
3、經過opencv 的源碼,從新編譯成 Android sdk 庫,這樣的好處是能獲取到最新的功能,缺點是編譯有點困難(對於不懂C++/C 的童鞋),且新的代碼或許會存在不兼容與錯誤。
 
     以上的連接是官網推薦的編譯過程,我也嘗試過編譯成功,若是在windows 下安裝Cygwin,而後來編譯是經過不了的,須要從新安裝cmake、shell 以及其它的軟件,編譯的過程確實複雜不少。
     我是在MAC下編譯的,只需安裝 cmake軟件,固然也要有NDK的環境。大概的步驟:
https://github.com/opencv/opencv 下載opencv 源碼包
 
一、在mac 下安裝好 cmake 軟件,
二、配置NDK環境變量, 參考百度: http://jingyan.baidu.com/article/d2b1d1029c1ea65c7e37d4c9.html
三、build_android_arm/install 目錄下 獲得編譯好的jni 目錄。
 
     若是你想編譯 opencv_contrib 也就是 opencv extra庫的話,你須要把 https://github.com/Itseez/opencv_contrib 額外庫包也下載下來。我曾經把opencv_contrib包的tracking模塊 加入到opencv 核心庫,編譯到PC的CodeBlocks開發環境就成功了,可是編譯成Android的環境就出錯了,這個問題我一直沒有解決,最後我換用了其它的方法,我把相應的一些資料提供給你們:
 
      我參考了上述的資料,在加載opencv 額外庫的時候,編譯了幾回也沒能成功,會報cmake 編譯出錯。我也讓C++ 的同事嘗試用cmake 幫我編譯,也沒能成功,也許咱們對cmake 瞭解不夠深,聽說opencv extra 庫是須要收費的,因此Android端不能直接編譯進來,可是PC端是成功編譯了的。若有編譯成功的大神,請多多指教!
相關文章
相關標籤/搜索