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

先說下題外話哈,最近做了個領取電商平臺優惠券的小程序,掃碼支持下哈~


image

最近看了一些opencv的相關內容,這里做一下記錄以及學習中的體會,和大家分享一下,本人在學習的時候也是網上查閱很多人的博客。

現在都是開源時代,opencv也是一個開源庫,也有官網和社區,所以簡介什么的大家去官網看看,了解什么是opencv,用來干什么的,這里就不羅嗦了。

1、下載

各個版本下載地址

可以根據自己的工作平臺下載對應的資源,本人實在android的領域下使用opencv,所以下載的是3.4.5 Android pack,后面的內容也是針對opencv在android開發中的使用。

opencv skd 版本

2、sdk結構

下載解壓后的文件結構如下

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靜態庫,有利于降低應用體積。

3、開發機制

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

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

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

  • 從應用本地包下面加載,要求相關的native層的庫、頭文件等要拷貝到項目工程中,并配置好,應用運行時就會按照配置從應用本地進行加載。
  • 設備上提前安裝 opencv-manager,是一個apk安裝包,以aidl的方式向其他應用提供opencv能力,所以開發應用時就不需要在拷貝native庫什么的到項目中,因為app運行時可以通過aidl方式,從opencv-manager中進行加載。

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

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

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

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

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

2、涉不涉及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能力不能滿足業務需求時使用這種方式。

4、開發實戰

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

1、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);

2、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();

3、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++。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372