opencv在android平臺下的開發【1】-android studio集成opencv-sdk

最近看了一些opencv的相關內容,這裏作一下記錄以及學習中的體會,和你們分享一下,本人在學習的時候也是網上查閱不少人的博客。html

如今都是開源時代,opencv也是一個開源庫,也有官網和社區,因此簡介什麼的你們去官網看看,瞭解什麼是opencv,用來幹什麼的,這裏就不羅嗦了。java

一、下載

各個版本下載地址python

能夠根據本身的工做平臺下載對應的資源,本人實在android的領域下使用opencv,因此下載的是3.4.5 Android pack,後面的內容也是針對opencv在android開發中的使用。android

opencv skd 版本

二、sdk結構

下載解壓後的文件結構以下c++

opencv sdk 文件結構

  • apk:這個包下面是opencv-manager安裝包,具體做用後面在細說。
  • samples:是opencv官方提供的幾個demo工程,有工程源代碼,也有打包好的apk。
  • sdk:這個是重點,之後開發的時候也是用的這裏面的東西。
    • etc:識別相關的級聯分類器之類的,目前我也不太懂,前期學習也用不到。
    • java:這是opencv官方提供的一個opencv的android庫工程,提供了完整的opencv能力,由於opencv底層是用c/c++寫的,可是如今編程語言不少,java、python等等,因此官方就針對不一樣的語言平臺,對底層庫進行了二次封裝,使用的時候將該該工程直接做爲庫導入便可,後面會細說。
    • native:一些native層的庫
      • 3rdparty:第三方的一些庫
      • jni:一些cmake編譯腳本和動態庫的頭文件
      • libs:官方根據不一樣平臺架構打好的.so動態庫,提供完整的opencv能力,體積稍大,單個架構對應的.so文件體積在10M以上
      • staticlibs:將不一樣的功能分別作成.a靜態庫,能夠根據使用到的opencv能力,選擇加載相應的.a靜態庫,有利於下降應用體積。

三、開發機制

opencv底層是c/c++寫的,語言門檻高,另外涉及的數學、圖形學等知識也加大了學習難度,因此官方針對不一樣水平和應用方向的人員提供了不一樣的開發方式,以造福廣大的opencv能力須要者。git

一、要不要在項目中配置sdk中native庫?github

在使用opencv能力以前,須要加載opencv提供的native庫,opencv提供了兩種方式:算法

  • 從應用本地包下面加載,要求相關的native層的庫、頭文件等要拷貝到項目工程中,並配置好,應用運行時就會按照配置從應用本地進行加載。
  • 設備上提早安裝 opencv-manager,是一個apk安裝包,以aidl的方式向其餘應用提供opencv能力,因此開發應用時就不須要在拷貝native庫什麼的到項目中,由於app運行時能夠經過aidl方式,從opencv-manager中進行加載。

爲何opencv要提供這兩種方式呢?編程

緣由就在於上面說過opencv的native庫文件體積比較大。api

若是是從本地包進行加載,設備上安裝的應用不少都使用opencv的話,每一個應用下都要拷貝一份native庫文件,浪費存儲空間,另外項目中配置native庫也相對繁瑣。

雖然設備上提早安裝 opencv-manager的方式節省了存儲空間,可是一個硬傷就是不能保證用戶設備上實現安裝了opencv-manager,再說了,用戶也不會爲了你的一個app而提早安裝另一個app,用戶纔不會聽你的。

因此,本身學習或者開發demo的時候能夠用提早安裝 opencv-manager的方式,省去了拷貝、配置native庫的操做,也節省了手機空間。可是若是開發正式的app仍是老老實實的從本地包加載爲好。

二、涉不涉及ndk開發?

android開發目前來講java還是主流,kotlin雖然愈來愈流行,可是對java是全兼容的。 opencv底層是c/c++實現的。 因此android中使用opencv能力就須要解決兩種語言通訊的問題,使用的方案固然是jni啦,opencvsdk的java工程對jni調用opencv方法進行了封裝,開發時直接調用封裝好的java方法便可實現opencv能力的調用,很爽吧,不用和c/c++打交道。

可是畢竟opencv底層是c/c++實現的,想要100%使用opencv的能力,或者sdk的java庫中提供的方法不能知足需求,仍是須要本身使用c/c++去實現一部分功能,自行封裝成jni方法使用。再說了如今都是團隊開發,能夠有專門的小夥伴實現底層的工做,對吧,這就須要拷貝、配置相關的native庫,使用ndk進行開發。

固然了,更厲害的大神能夠下載源碼進行修改,自行編譯,不只能夠獲得最新的sdk,並且可以根據須要,自行實現底層相關算法之類的。

這裏對不一樣的開發機制的適用場景進行簡單的總結:

  1. java庫+opencv-manager.apk:適用於我的學習或者作demo,在設備上事先安裝opencv-manager.apk,而後項目中導入java庫工程,便可進行後續開發。
  2. java庫+native庫:對opencv能力沒有特殊要求的狀況下,開發線上應用。
  3. java庫+native庫+自行封裝實現的jni方法:開發線上應用,可是java庫提供的opencv能力不能知足業務需求時使用這種方式。

四、開發實戰

通過上面的討論,對android下opencv的開發機制有了大概瞭解,下面的分別對幾種開發方式進行簡單的實現。

一、java庫+opencv-manager.apk

準備

須要準備的東西是sdk的java庫工程以及設備平臺對應的opencv-manager.apk

配置

  1. 在設備上安裝opencv-manager.apk
  2. 在android studio中新建一個工程,已經有的話直接打開
  3. 導入sdk的java庫工程:File-New-Import module,定位到java庫工程,導入後庫工程的module name 爲openCVLibrary343
  4. 配置主module依賴openCVLibrary343:在主modlue的guild.gradle文件的dependencies節點下添加implementation project(':openCVLibrary343'),而後同步代碼便可。

開發

在 Activity 的 onResume 方法中初始化opencv

//使用OpenCV Engine service,須要運行設備事先安裝OpenCV Manager
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                if (status == LoaderCallbackInterface.SUCCESS) {
                    Log.d(TAG, "onManagerConnected: success");
                } else {
                    super.onManagerConnected(status);
                }
            }
        });
複製代碼

對圖片進行均值模糊

//本地加載圖片
Bitmap originImg = BitmapFactory.decodeFile("filePath");
//初始化Mat
Mat src = new Mat(originImg.getHeight(), originImg.getWidth(), CvType.CV_8UC4);
//bitmap轉mat
Utils.bitmapToMat(originImg, src);
//均值模糊
Imgproc.blur(src, src, new Size(3, 3));
//初始化處理後bitmap
Bitmap processedImg = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
//mat轉bitmap
Utils.matToBitmap(src, processedImg);
複製代碼

二、java庫+native庫

和上種方式的區別在於:

  • 不須要事先安裝opencv-manager.apk
  • 須要在項目中配置native庫

準備

須要準備的東西是sdk的java庫工程、native庫(sdk-native-libs)

配置

  1. 導入java庫工程,並配置依賴,具體步驟在【java庫+opencv-manager.apk】開發方式中有描述
  2. 將libs文件夾複製拷貝到項目工程的src-main-jniLibs路徑下,若是jniLis文件夾不存在就本身新建一個
  3. 打開module的build.gradle文件,在 android 節點下添加以下代碼,而後同步代碼便可
sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs/libs']
        }
    }
複製代碼

開發

和【java庫+opencv-manager.apk】開發方式初始化opencv的時候有區別,其餘都同樣。

在 Activity 的 onResume 方法中初始化opencv

//使用應用本地native庫
        OpenCVLoader.initDebug();
複製代碼

三、java庫+native庫+自行封裝實現的jni方法

這種方式是在【java庫+native庫】開發方式的基礎上使用ndk進行jni開發。

準備

須要準備的東西是sdk的java庫工程、native庫(sdk-native-libs)、native庫頭文件(sdk-native-jni-include)

配置

  1. 參考博客【音視頻開發01–AS3.x NDK開發環境搭建】創建支持ndk開發的項目。
  2. 完成【java庫+native庫】開發方式中的相關配置。
  3. 將native庫頭文件(sdk-native-jni-include)拷貝到src-main-cpp目錄下(若是沒有該目錄,請先按照【音視頻開發01–AS3.x NDK開發環境搭建】的過程進行操做)
  4. 編輯 CMakeLists.txt 文件內容(若是沒有該文件,請先按照【音視頻開發01–AS3.x NDK開發環境搭建】的過程進行操做)
  5. 配置比較繁瑣,若是出現問題,請積極搜索,學習android studio cmake ndk開發的相關知識。
cmake_minimum_required(VERSION 3.4.1)

include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

add_library(libopencv_java3 SHARED IMPORTED)
set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION
             ${CMAKE_SOURCE_DIR}/src/main/jniLibs/libs/${ANDROID_ABI}/libopencv_java3.so)

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 )

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.
                       native-lib libopencv_java3

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
複製代碼

開發

demo吧,就是jni開發那一套。

總結

android中使用opencv進行開發時,針對不一樣的開發和應用場景選擇開發方式,總的來講涉及的東西挺多的,android知識、ndk/jni知識、c/c++知識、opencv知識、數學知識等。

學習的時候以android 開發爲基礎,經過本文搭建起開發框架,在寫demo的過程當中學習opencv api和相關的理論知識,同時也學習了ndk/jni和c/c++。

相關文章
相關標籤/搜索