opencv在android平臺(tái)下的開發(fā)【1】-android studio集成opencv-sdk

先說下題外話哈,最近做了個(gè)領(lǐng)取電商平臺(tái)優(yōu)惠券的小程序,掃碼支持下哈~


image

最近看了一些opencv的相關(guān)內(nèi)容,這里做一下記錄以及學(xué)習(xí)中的體會(huì),和大家分享一下,本人在學(xué)習(xí)的時(shí)候也是網(wǎng)上查閱很多人的博客。

現(xiàn)在都是開源時(shí)代,opencv也是一個(gè)開源庫,也有官網(wǎng)和社區(qū),所以簡介什么的大家去官網(wǎng)看看,了解什么是opencv,用來干什么的,這里就不羅嗦了。

1、下載

各個(gè)版本下載地址,

可以根據(jù)自己的工作平臺(tái)下載對(duì)應(yīng)的資源,本人實(shí)在android的領(lǐng)域下使用opencv,所以下載的是3.4.5 Android pack,后面的內(nèi)容也是針對(duì)opencv在android開發(fā)中的使用。

opencv skd 版本

2、sdk結(jié)構(gòu)

下載解壓后的文件結(jié)構(gòu)如下

opencv sdk 文件結(jié)構(gòu)
  • apk:這個(gè)包下面是opencv-manager安裝包,具體作用后面在細(xì)說。
  • samples:是opencv官方提供的幾個(gè)demo工程,有工程源代碼,也有打包好的apk。
  • sdk:這個(gè)是重點(diǎn),以后開發(fā)的時(shí)候也是用的這里面的東西。
    • etc:識(shí)別相關(guān)的級(jí)聯(lián)分類器之類的,目前我也不太懂,前期學(xué)習(xí)也用不到。
    • java:這是opencv官方提供的一個(gè)opencv的android庫工程,提供了完整的opencv能力,因?yàn)閛pencv底層是用c/c++寫的,但是現(xiàn)在編程語言很多,java、python等等,所以官方就針對(duì)不同的語言平臺(tái),對(duì)底層庫進(jìn)行了二次封裝,使用的時(shí)候?qū)⒃撛摴こ讨苯幼鳛閹鞂?dǎo)入即可,后面會(huì)細(xì)說。
    • native:一些native層的庫
      • 3rdparty:第三方的一些庫
      • jni:一些cmake編譯腳本和動(dòng)態(tài)庫的頭文件
      • libs:官方根據(jù)不同平臺(tái)架構(gòu)打好的.so動(dòng)態(tài)庫,提供完整的opencv能力,體積稍大,單個(gè)架構(gòu)對(duì)應(yīng)的.so文件體積在10M以上
      • staticlibs:將不同的功能分別做成.a靜態(tài)庫,可以根據(jù)使用到的opencv能力,選擇加載相應(yīng)的.a靜態(tài)庫,有利于降低應(yīng)用體積。

3、開發(fā)機(jī)制

opencv底層是c/c++寫的,語言門檻高,另外涉及的數(shù)學(xué)、圖形學(xué)等知識(shí)也加大了學(xué)習(xí)難度,所以官方針對(duì)不同水平和應(yīng)用方向的人員提供了不同的開發(fā)方式,以造福廣大的opencv能力需要者。

1、要不要在項(xiàng)目中配置sdk中native庫?

在使用opencv能力之前,需要加載opencv提供的native庫,opencv提供了兩種方式:

  • 從應(yīng)用本地包下面加載,要求相關(guān)的native層的庫、頭文件等要拷貝到項(xiàng)目工程中,并配置好,應(yīng)用運(yùn)行時(shí)就會(huì)按照配置從應(yīng)用本地進(jìn)行加載。
  • 設(shè)備上提前安裝 opencv-manager,是一個(gè)apk安裝包,以aidl的方式向其他應(yīng)用提供opencv能力,所以開發(fā)應(yīng)用時(shí)就不需要在拷貝native庫什么的到項(xiàng)目中,因?yàn)閍pp運(yùn)行時(shí)可以通過aidl方式,從opencv-manager中進(jìn)行加載。

為什么opencv要提供這兩種方式呢?

原因就在于上面說過opencv的native庫文件體積比較大。

如果是從本地包進(jìn)行加載,設(shè)備上安裝的應(yīng)用很多都使用opencv的話,每個(gè)應(yīng)用下都要拷貝一份native庫文件,浪費(fèi)存儲(chǔ)空間,另外項(xiàng)目中配置native庫也相對(duì)繁瑣。

雖然設(shè)備上提前安裝 opencv-manager的方式節(jié)省了存儲(chǔ)空間,但是一個(gè)硬傷就是不能保證用戶設(shè)備上實(shí)現(xiàn)安裝了opencv-manager,再說了,用戶也不會(huì)為了你的一個(gè)app而提前安裝另外一個(gè)app,用戶才不會(huì)聽你的。

所以,自己學(xué)習(xí)或者開發(fā)demo的時(shí)候可以用提前安裝 opencv-manager的方式,省去了拷貝、配置native庫的操作,也節(jié)省了手機(jī)空間。但是如果開發(fā)正式的app還是老老實(shí)實(shí)的從本地包加載為好。

2、涉不涉及ndk開發(fā)?

android開發(fā)目前來說java仍是主流,kotlin雖然越來越流行,但是對(duì)java是全兼容的。 opencv底層是c/c++實(shí)現(xiàn)的。 所以android中使用opencv能力就需要解決兩種語言通信的問題,使用的方案當(dāng)然是jni啦,opencvsdk的java工程對(duì)jni調(diào)用opencv方法進(jìn)行了封裝,開發(fā)時(shí)直接調(diào)用封裝好的java方法即可實(shí)現(xiàn)opencv能力的調(diào)用,很爽吧,不用和c/c++打交道。

但是畢竟opencv底層是c/c++實(shí)現(xiàn)的,想要100%使用opencv的能力,或者sdk的java庫中提供的方法不能滿足需求,還是需要自己使用c/c++去實(shí)現(xiàn)一部分功能,自行封裝成jni方法使用。再說了現(xiàn)在都是團(tuán)隊(duì)開發(fā),可以有專門的小伙伴實(shí)現(xiàn)底層的工作,對(duì)吧,這就需要拷貝、配置相關(guān)的native庫,使用ndk進(jìn)行開發(fā)。

當(dāng)然了,更厲害的大神可以下載源碼進(jìn)行修改,自行編譯,不僅可以得到最新的sdk,而且能夠根據(jù)需要,自行實(shí)現(xiàn)底層相關(guān)算法之類的。

這里對(duì)不同的開發(fā)機(jī)制的適用場景進(jìn)行簡單的總結(jié):

  1. java庫+opencv-manager.apk:適用于個(gè)人學(xué)習(xí)或者做demo,在設(shè)備上事先安裝opencv-manager.apk,然后項(xiàng)目中導(dǎo)入java庫工程,即可進(jìn)行后續(xù)開發(fā)。
  2. java庫+native庫:對(duì)opencv能力沒有特殊要求的情況下,開發(fā)線上應(yīng)用。
  3. java庫+native庫+自行封裝實(shí)現(xiàn)的jni方法:開發(fā)線上應(yīng)用,但是java庫提供的opencv能力不能滿足業(yè)務(wù)需求時(shí)使用這種方式。

4、開發(fā)實(shí)戰(zhàn)

經(jīng)過上面的討論,對(duì)android下opencv的開發(fā)機(jī)制有了大概了解,下面的分別對(duì)幾種開發(fā)方式進(jìn)行簡單的實(shí)現(xiàn)。

1、java庫+opencv-manager.apk

準(zhǔn)備

需要準(zhǔn)備的東西是sdk的java庫工程以及設(shè)備平臺(tái)對(duì)應(yīng)的opencv-manager.apk

配置

  1. 在設(shè)備上安裝opencv-manager.apk
  2. 在android studio中新建一個(gè)工程,已經(jīng)有的話直接打開
  3. 導(dǎo)入sdk的java庫工程:File-New-Import module,定位到j(luò)ava庫工程,導(dǎo)入后庫工程的module name 為openCVLibrary343
  4. 配置主module依賴openCVLibrary343:在主modlue的guild.gradle文件的dependencies節(jié)點(diǎn)下添加implementation project(':openCVLibrary343'),然后同步代碼即可。

開發(fā)

在 Activity 的 onResume 方法中初始化opencv

        //使用OpenCV Engine service,需要運(yùn)行設(shè)備事先安裝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);
                }
            }
        });

對(duì)圖片進(jìn)行均值模糊

//本地加載圖片
Bitmap originImg = BitmapFactory.decodeFile("filePath");
//初始化Mat
Mat src = new Mat(originImg.getHeight(), originImg.getWidth(), CvType.CV_8UC4);
//bitmap轉(zhuǎn)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轉(zhuǎn)bitmap
Utils.matToBitmap(src, processedImg);

2、java庫+native庫

和上種方式的區(qū)別在于:

  • 不需要事先安裝opencv-manager.apk
  • 需要在項(xiàng)目中配置native庫

準(zhǔn)備

需要準(zhǔn)備的東西是sdk的java庫工程、native庫(sdk-native-libs)

配置

  1. 導(dǎo)入java庫工程,并配置依賴,具體步驟在【java庫+opencv-manager.apk】開發(fā)方式中有描述
  2. 將libs文件夾復(fù)制拷貝到項(xiàng)目工程的src-main-jniLibs路徑下,如果jniLis文件夾不存在就自己新建一個(gè)
  3. 打開module的build.gradle文件,在 android 節(jié)點(diǎn)下添加如下代碼,然后同步代碼即可
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs/libs']
        }
    }

開發(fā)

和【java庫+opencv-manager.apk】開發(fā)方式初始化opencv的時(shí)候有區(qū)別,其他都一樣。

在 Activity 的 onResume 方法中初始化opencv

        //使用應(yīng)用本地native庫
        OpenCVLoader.initDebug();

3、java庫+native庫+自行封裝實(shí)現(xiàn)的jni方法

這種方式是在【java庫+native庫】開發(fā)方式的基礎(chǔ)上使用ndk進(jìn)行jni開發(fā)。

準(zhǔn)備

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

配置

  1. 參考博客【音視頻開發(fā)01–AS3.x NDK開發(fā)環(huán)境搭建】建立支持ndk開發(fā)的項(xiàng)目。
  2. 完成【java庫+native庫】開發(fā)方式中的相關(guān)配置。
  3. 將native庫頭文件(sdk-native-jni-include)拷貝到src-main-cpp目錄下(如果沒有該目錄,請(qǐng)先按照【音視頻開發(fā)01–AS3.x NDK開發(fā)環(huán)境搭建】的過程進(jìn)行操作)
  4. 編輯 CMakeLists.txt 文件內(nèi)容(如果沒有該文件,請(qǐng)先按照【音視頻開發(fā)01–AS3.x NDK開發(fā)環(huán)境搭建】的過程進(jìn)行操作)
  5. 配置比較繁瑣,如果出現(xiàn)問題,請(qǐng)積極搜索,學(xué)習(xí)android studio cmake ndk開發(fā)的相關(guān)知識(shí)。
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} )

開發(fā)

demo吧,就是jni開發(fā)那一套。

總結(jié)

android中使用opencv進(jìn)行開發(fā)時(shí),針對(duì)不同的開發(fā)和應(yīng)用場景選擇開發(fā)方式,總的來說涉及的東西挺多的,android知識(shí)、ndk/jni知識(shí)、c/c++知識(shí)、opencv知識(shí)、數(shù)學(xué)知識(shí)等。

學(xué)習(xí)的時(shí)候以android 開發(fā)為基礎(chǔ),通過本文搭建起開發(fā)框架,在寫demo的過程中學(xué)習(xí)opencv api和相關(guān)的理論知識(shí),同時(shí)也學(xué)習(xí)了ndk/jni和c/c++。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容