1. 程式人生 > >Ubuntu 16.04下為Android編譯OpenCV 3.2.0 Manager

Ubuntu 16.04下為Android編譯OpenCV 3.2.0 Manager

由於 ica 如何 setting -i add 標記 roi stripe

http://johnhany.net/2016/07/build-opencv-manager-for-android-on-ubuntu/

最近想在Android上嘗試一下SIFT和SURF匹配算法,但考慮到這些算法都是專利保護的,並沒有被包含在預編譯庫中,所以還需要自己來動手編譯OpenCV Android SDK。在OpenCV 2.4.x版本中,這些算法被包含在nonfree模塊中;從3.0版本開始,用於圖像特征匹配的一些算法(比如SIFT,SURF,BRIEF,FREAK等)被轉移到了opencv_contrib項目的xfeatures2d模塊中。在PC環境下,為C++編譯opencv+contrib庫是很方便的,不過為Android平臺的編譯過程就有些麻煩了。

我在編譯的過程中也遇到了一些問題,在網絡上搜索相應解決方案時也發現很多人都在嘗試為OpenCV Android SDK添加contrib(nonfree)支持,某些遇到難以解決的問題最後只能繞路而行,比如這裏和這裏。我找到相應解決辦法後回應了他們,但願對別人會有所幫助吧!

本文要介紹的內容就是如何在Ubuntu 16.04環境下利用最新的OpenCV和opencv_contrib為Android平臺編譯一個可用的OpenCV Android SDK,並生成相應的OpenCV Manager。

2017.08.03更新:

更新到OpenCV 3.2,Android SDK API 24,Android NDK r15b。

我原本掙紮了三天嘗試在Windows平臺通過MinGW來編譯最新版本的OpenCV Android SDK,但在生成Manager的apk時遇到很棘手的問題,只好作罷轉回Linux進行編譯。不過讀者放心,在Linux下編譯得到的OpenCV Android SDK也可在Windows下直接使用,另外我在文章結尾添加了我編譯好的SDK下載鏈接。

我的開發環境如下:

Ubuntu 16.04 LTS (x64)

GCC 5.4.0

CMAKE 3.9.0

OpenCV 3.2.0

Android SDK API 24(Android 7.0)

Android SDK Tools r25.2.2

Androird NDK r15b

Python 3.5

雖然目前Android SDK Tools已經更新到r26,但由於其相對原來的工具變化較大,為了穩妥起見,建議手動降級到r25版本(下載地址:https://dl.google.com/android/repository/tools_r25.2.2-linux.zip)

當然在編譯過程中還會用到很多其他工具和軟件包,比如Ninja,Ant等,我會在文中需要的時候給出它們的版本和安裝方法。

關於GCC,CMAKE和Python的安裝過程本文就不詳述了,一是因為這些工具的安裝過程很容易,網絡上的介紹都很詳細,二是因為之前剛剛配置好TensorFlow,安裝了一大堆軟件包,我也不清楚本文的內容究竟會涉及哪些依賴庫,我會盡量把我在編譯過程中所需的工具和庫標記出來。

同樣,Android SDK和NDK的安裝方法這裏也不會作過多介紹。我是通過Android Studio 2.1.2提供的SDK Manager下載的Android SDK和Android NDK,在Android Studio中下載Android SDK和Android NDK的方法可以參考《Android Studio 2上利用NDK進行OpenCV 3.1開發》,雖然開發平臺不同,但在軟件界面中的操作過程是相似的。我的Android SDK路徑是/home/john/Android/Sdk,Android NDK的路徑是/home/john/Android/Sdk/ndk-bundle。


下載源碼

在opencv的master分支Release頁面下載opencv 3.2源碼,解壓到一個有讀寫權限的目錄下,比如/home/john/Downloads/opencv-master。在這裏下載對應3.2的opencv-contrib源碼,解壓到某個目錄下,個人習慣是解壓到OpenCV的源碼根目錄下,使得opencv-contrib/modules目錄的路徑如/home/john/Downloads/opencv-master/opencv_contrib/modules,這個路徑後面會用到。

個人推薦在編譯其他OpenCV版本甚至編譯其他軟件包時要下載有版本號的Release版,而不是直接git下來最新的master版。畢竟master一般是正在開發修繕的版本,即便是整合了功能強大的CI(比如OpenCV在用的buildbot,或者其他開源庫喜歡用的travis-ci)也不能保證其測試過程考慮到了大多數應用環境。

如果你的機器上已經有了一份opencv源碼,但不想花時間去下載最新版本,至少要保證你的opencv源碼是在16年5月份之後下載的(具體來講,至少要包含該Pull Request:Added –extra_modules_path to build_sdk.py #6460,這樣你的build_sdk.py才會包含後面要用到的extra_modules_path)。

僅僅下載好源碼還不夠,還要對源碼做一些修改,具體如下:

1.把/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/include/opencv2目錄下的xfeatures2d.hpp文件和xfeatures2d文件夾復制到/home/john/Downloads/opencv-master/modules/features2d/include/opencv2目錄下。此時,該目錄包含的文件應該如下圖所示:

技術分享圖片 2.找到/home/john/Downloads/opencv-master/modules/features2d/misc/java/src/cpp目錄,打開features2d_manual.hpp文件,做以下修改:

在第8行增加一個頭文件opencv2/xfeatures2d.hpp,即把

1 2 3 #ifdef HAVE_OPENCV_FEATURES2D #include "opencv2/features2d.hpp" #include "features2d_converters.hpp"

改為

1 2 3 4 #ifdef HAVE_OPENCV_FEATURES2D #include "opencv2/features2d.hpp" #include "opencv2/xfeatures2d.hpp" #include "features2d_converters.hpp"

把第120-125行的

1 2 3 4 5 6 //case SIFT: // name = name + "SIFT"; // break; //case SURF: // name = name + "SURF"; // break;

改為

1 2 3 4 5 6 case SIFT: fd = xfeatures2d::SIFT::create(); break; case SURF: fd = xfeatures2d::SURF::create(); break;

把第239-245行的

1 2 3 4 5 6 //case SIFT: // name = name + "SIFT"; // break; //case SURF: // name = name + "SURF"; // break;

改為

1 2 3 4 5 6 case SIFT: de = xfeatures2d::SIFT::create(); break; case SURF: de = xfeatures2d::SURF::create(); break;

把第254-256行的

1 2 3 //case FREAK: // name = name + "FREAK"; // break;

改為

1 2 3 case FREAK: de = xfeatures2d::FREAK::create(); break;


編譯OpenCV Android SDK

找到/home/john/Downloads/opencv-master/platforms/android目錄,在該目錄下會發現build_sdk.py文件,這個文件就是用來編譯OpenCV Android SDK的Python腳本文件。

首先做一些檢查工作:

1.在第78行的ABIs定義了需要編譯的ABI目標以及相應的NDK工具鏈。保險起見,可以先在/home/john/Android/Sdk/ndk-bundle/toolchains中查看一下你的NDK工具鏈版本,如果版本號有所不同,就要修改build_sdk.py中對應ABI工具鏈的版本,如下圖所示:

技術分享圖片 mips和mips64兩行被註釋掉的原因是,在我的機器上編譯時,由於依賴庫之一Google Protobuf的編譯錯誤,無法為這兩個架構成功編譯OpenCV Android SDK。不過我手邊並沒有采用該架構的Android設備,而且我暫時還不需要考慮短期內編寫的代碼有太好的兼容性,所以幹脆放棄對這兩種架構進行編譯。如果感興趣,你可以試著為mips編譯一下:)目前在編譯OpenCV 3.2版本時,所有ABI都能夠成功編譯(包括:arm64-v8a,armeabi,armeabi-v7a,mips,mips64,x86,x86_64)。上圖並沒有相應更新,還請見諒!

2.安裝Ninja。打開終端,輸入:

1 sudo apt-get install ninja-build

另外,我在編譯之前參考這裏又安裝了幾個用於交叉編譯的庫,不確定是否必要,但還是貼出來吧:

1 sudo apt-get install gcc-4.9-arm-linux-gnueabihf

其中版本號4.9根據你的NDK工具鏈的版本來修改(工具鏈路徑在android-sdk\ndk-bundle\toolchains當中)。

3.安裝Ant。在終端輸入:

1 sudo apt-get install ant

如果不安裝Ant,在編譯過程中CMAKE關於Java的輸出信息全是NO,而且後面還會出現unknown target ‘opencv_engine‘的錯誤。

4.在build_sdk.py裏還有很多可以根據需要來修改的地方,比如-DANDROID_NATIVE_API_LEVEL可以適當地提高,可以選擇開啟-DBUILD_EXAMPLES和-DBUILD_TESTS等等。這裏為了演示的目的,除了前文提到的,其他地方全部保持默認,不做修改。

5.在終端中輸入:

1 python /home/john/Downloads/opencv-master/platforms/android/build_sdk.py /home/john/Downloads/opencv-master/build /home/john/Downloads/opencv-master --sdk_path=/home/john/Android/Sdk --ndk_path=/home/john/Android/Sdk/ndk-bundle --extra_modules_path=/home/john/Downloads/opencv-master/opencv_contrib/modules

註意命令是一行的,中間沒有換行符。

根據build_sdk.py文件中第252行的說明,其采用的參數按照以下格式:

1 python build_sdk.py <output-dir> <opencv-src-dir> --sdk_path=<android-sdk-path> --ndk_path=<ndk-path> --extra_modules_path=<opencv-contrib-path>

其中,<output-dir>是保存編譯中間結果和最終結果的目錄(也叫工作目錄),<android-sdk-path>指向OpenCV源碼目錄,<android-sdk-path>為Android SDK目錄,<ndk-path>為Android NDK目錄,<opencv-contrib-path>為opencv_contrib/modules所在的路徑。


結果

最終,在/home/john/Downloads/opencv-master/build目錄中會得到一個名為OpenCV-android-sdk的文件夾,這就是你編譯得到的OpenCV Android SDK。和官方預編譯庫一樣,在apk子文件夾中是OpenCV Manager的安裝包,在sdk/java文件夾中是OpenCV的Java接口,sdk/native是OpenCV的Native接口。

在新項目中使用自己編譯的OpenCV Android SDK時,要註意需要在設備上重新安裝OpenCV Manager,還要修改Android.mk中指向OpenCV.mk的路徑。

技術分享圖片

如果需要調用SIFT,SURF等匹配算法,還要把相應的源碼文件(位於/home/john/Downloads/opencv-master/opencv_contrib/modules/xfeatures2d/src)拷貝到項目jni文件夾中,然後在Android.mk中為LOCAL_SRC_FILES添加對應的源碼文件。

在編譯的過程中如果發現有錯誤或異常出現,可以首先比較一下OpenCV官方BuildBot的輸出信息,便於分析自己的問題原因。最新編譯結果的鏈接為:http://pullrequest.opencv.org/buildbot/one_line_per_build。一次編譯成功的輸出結果為precommit_pack_android Build Log #116。如果你的網絡比較好,甚至可以把網站上生成的壓縮包下載下來(比如這裏)!

我編譯產生的OpenCV Android SDK可以在這裏下載:http://pan.baidu.com/s/1kVOejLt。因為考慮到在編譯過程中需要從網絡下載一些文件,我已經把Linux與Windows編譯所需的文件全部下載好,並和3.2的源碼一同放在sources文件夾中。感興趣的讀者可以直接用這個源碼包進行編譯。

另外附上一篇在Android上利用SIFT,SURF和FREAK進行目標匹配的教程:《深入OpenCV Android應用開發 中文版 – 第三章代碼更新》。


參考資料

[1] http://stackoverflow.com/questions/30657774/surf-and-sift-algorithms-doesnt-work-in-opencv-3-0-java

[2] https://github.com/opencv/opencv/issues/5561

[3] https://github.com/opencv/opencv/issues/6215

[4] http://answers.opencv.org/question/73863/how-to-run-build_sdkpy-for-android-sdk/

[5] https://zami0xzami.wordpress.com/2016/03/17/building-opencv-for-android-from-source/

[6] http://eevee.cc/2017/05/05/build-ocv-for-android-with-cuda/

Ubuntu 16.04下為Android編譯OpenCV 3.2.0 Manager