標籤:ring des .net 地方 環境 dma win tool string
前文曾具體探討了關於OpenCV的使用,原本以為天下已太平。但不斷有人反應依舊配不好OpenCV4Android,不能得心應手的在Android上使用OpenCV。大量的精力都浪費在摸索配置上。尤其是OpenCVManager誕生之後。更讓人無語。大家第一個反應就是怎樣才幹不安裝OpenCVManager。由於要多安裝這個東西對客戶來說體驗太不好了。
咱家昨夜研究至兩點,今早七點起床。最終把頭緒理清了。
以下咱家以之前做過的一個基於OpenCV2.3.1。android通過jni調用opencv實現人臉檢測的執行個體來逐個回答,怎樣在Android上使用Java介面而不安裝OpenCVManager,及通過jni方式使用OpenCV的三種方式。
先來看JNI調OpenCV的三種方式。非常多人會驚訝腫麼JNI調OpenCV還會有3種方式。長久以來大量網上教程都說在Android上僅僅有Java和JNI兩種方式使用OpenCV,怎麼又冒出來3種使用JNI的方式。
經本人研究。確實有3種調JNI的方式,就連官網指導文檔都模稜兩可,所以讓非常多人不知所措。
這三種方式各自是:
1、使用靜態OpenCV庫的方式。
2、使用動態OpenCV庫的方式;
3、同一時候使用Java的API又使用JNI的介面的方式,此時編譯時間一般使用的是動態連結OpenCV庫的方式。
要說明的是,這三種方式均無需安裝OpenCVManager,差別在於mk檔案的不同。個人最推崇的就是第一種方式,第一種方式也是和OpenCV2.3.1在JNI調OpenCV使用全然吻合的一種方式。本文是以windows平台最新的OpenCV-2.4.9-android-sdk為基礎,使用2.4.9的OpenCV4Android須要使用NDK版本號碼為r9,本人使用的是android-ndk-r9d的版本號碼。之所以昨晚搗騰到2點,就是由於之前使用的ndk r7的版本號碼。怎麼編都編只是,因少東西報上千行錯誤。android-ndk-r9d安裝十分簡單,僅僅須要解壓縮配置一個環境變數就可以。
一、Android以JNI調OpenCV的第一種配置方法:
Application.mk檔案中的內容例如以下:
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI:= armeabi-v7a
這三種方式的Application.mk都一樣,所以往後不說了。在Application.mk裡還能夠配置APP_PLATFORM=17相似這樣的,當然不配置全然能夠。
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 D:\ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ProcessImg
LOCAL_SRC_FILES := DetectFace_JNI.cpp \
src/copyToAssets.cpp \
src/detectFace.cpp
LOCAL_LDLIBS += -lm -llog
include $(BUILD_SHARED_LIBRARY)
逐一解釋下,OpenCV_INSTALL_MODULES:=on的意思是自己主動將依賴的OpenCV的so庫複製到libs目錄下,但非常遺憾的是,這個命令僅僅對OPENCV_CAMERA_MODULES有效。
僅僅有當OPENCV_CAMERA_MODULES:=on時。能夠看到他會自己主動將裡面的帶camera的so拷貝至project下的libs目錄下。include D:\ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk這句話比較關鍵,這是我安裝OpenCV-2.4.9-android-sdk的地方。我將其安裝到了D盤。而我的工作空間在E盤也是ok的。
而不用像OpenCV2.3.1使用時,限制這個解壓縮包的位置了。
LOCAL_MODULE 是要產生的庫的名字,LOCAL_SRC_FILES 是jni目錄下的cpp檔案。當中的src說明我的jni下還有個子目錄名字是“src”,這塊替換成自己的原始碼檔案就ok了。
為了測試的嚴謹性。在project裡將libs目錄的東西。和obj目錄下的東西全刪了。用cygwin進到project,輸入ndk-build,看到例如以下資訊:
[email protected] /cygdrive/e/WorkSpaces/OpenCV4Android/FaceDetectLiu2$ ndk-buildAndroid NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 16 in ./AndroidManifest.xml[armeabi-v7a] Cygwin : Generating dependency file converter script[armeabi-v7a] Compile++ thumb: ProcessImg <= DetectFace_JNI.cppjni/DetectFace_JNI.cpp: In function ‘_jstring* Java_org_yan_processlib_LibProcessImg_processIplImg(JNIEnv*, jobject, jintArray, int, int)‘:jni/DetectFace_JNI.cpp:99:44: warning: converting ‘false‘ to pointer type for argument 2 of ‘jint* _JNIEnv::GetIntArrayElements(jintArray, jboolean*)‘ [-Wconversion-null]jni/DetectFace_JNI.cpp: In function ‘_jstring* Java_org_yan_processlib_LibProcessImg_processStaticImg(JNIEnv*, jobject, jintArray, int, int)‘:jni/DetectFace_JNI.cpp:133:44: warning: converting ‘false‘ to pointer type for argument 2 of ‘jint* _JNIEnv::GetIntArrayElements(jintArray, jboolean*)‘ [-Wconversion-null][armeabi-v7a] Compile++ thumb: ProcessImg <= copyToAssets.cpp[armeabi-v7a] Compile++ thumb: ProcessImg <= detectFace.cpp[armeabi-v7a] SharedLibrary : libProcessImg.so[armeabi-v7a] Install : libProcessImg.so => libs/armeabi-v7a/libProcessImg.so
上面兩個警告麼有關係,編譯成功。產生的libProcessImg.so的大小為4M,整個apk大小為1.99M。
注意,假設將mk裡的LOCAL_LDLIBS += -lm -llog這一句錯誤的寫為:LOCAL_LDLIBS := -lm -llog。即將“+=”錯寫成了“:=”將會看到例如以下大量錯誤:
$ ndk-buildAndroid NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 16 in ./AndroidManifest.xml[armeabi-v7a] Compile++ thumb: ProcessImg <= DetectFace_JNI.cppjni/DetectFace_JNI.cpp: In function ‘_jstring* Java_org_yan_processlib_LibProcessImg_processIplImg(JNIEnv*, jobject, jintArray, int, int)‘:jni/DetectFace_JNI.cpp:99:44: warning: converting ‘false‘ to pointer type for argument 2 of ‘jint* _JNIEnv::GetIntArrayElements(jintArray, jboolean*)‘ [-Wconversion-null]jni/DetectFace_JNI.cpp: In function ‘_jstring* Java_org_yan_processlib_LibProcessImg_processStaticImg(JNIEnv*, jobject, jintArray, int, int)‘:jni/DetectFace_JNI.cpp:133:44: warning: converting ‘false‘ to pointer type for argument 2 of ‘jint* _JNIEnv::GetIntArrayElements(jintArray, jboolean*)‘ [-Wconversion-null][armeabi-v7a] Compile++ thumb: ProcessImg <= copyToAssets.cpp[armeabi-v7a] Compile++ thumb: ProcessImg <= detectFace.cpp[armeabi-v7a] SharedLibrary : libProcessImg.soD:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function icvGets(CvFileStorage*, char*, int):persistence.cpp(.text._ZL7icvGetsP13CvFileStoragePci+0x7e): error: undefined reference to ‘gzgets‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function icvXMLSkipSpaces(CvFileStorage*, char*, int):persistence.cpp(.text._ZL16icvXMLSkipSpacesP13CvFileStoragePci+0x1c4): error: undefined reference to ‘gzeof‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function icvYMLSkipSpaces(CvFileStorage*, char*, int, int) [clone .constprop.65]:persistence.cpp(.text._ZL16icvYMLSkipSpacesP13CvFileStoragePcii.constprop.65+0x122): error: undefined reference to ‘gzeof‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function icvPuts(CvFileStorage*, char const*):persistence.cpp(.text._ZL7icvPutsP13CvFileStoragePKc+0x32): error: undefined reference to ‘gzputs‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function icvClose(CvFileStorage*, std::string*):persistence.cpp(.text._ZL8icvCloseP13CvFileStoragePSs+0x132): error: undefined reference to ‘gzclose‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function cvOpenFileStorage:persistence.cpp(.text.cvOpenFileStorage+0x1ac): error: undefined reference to ‘gzrewind‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function cvOpenFileStorage:persistence.cpp(.text.cvOpenFileStorage+0x6d4): error: undefined reference to ‘gzclose‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function cvOpenFileStorage:persistence.cpp(.text.cvOpenFileStorage+0x75a): error: undefined reference to ‘gzopen‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function cvOpenFileStorage:persistence.cpp(.text.cvOpenFileStorage+0xd80): error: undefined reference to ‘gzclose‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../3rdparty/libs/armeabi-v7a/liblibpng.a(pngread.c.o): in function png_create_read_struct_2:pngread.c(.text.png_create_read_struct_2+0x112): error: undefined reference to ‘inflateInit_‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../3rdparty/libs/armeabi-v7a/liblibpng.a(pngread.c.o): in function png_read_row:pngread.c(.text.png_read_row+0x218): error: undefined reference to ‘inflate‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../3rdparty/libs/armeabi-v7a/liblibpng.a(pngread.c.o): in function png_read_destroy:pngread.c(.text.png_read_destroy+0x96): error: undefined reference to ‘inflateEnd‘D:/ProgramFile/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\/../3rdparty/libs/armeabi-v7a/liblibpng.a(pngwrite.c.o): in function png_write_flush:pngwrite.c(.text.png_write_flush+0x1c): error: undefined reference to ‘deflate‘
上兩張執行,各自是預覽介面檢測人臉和拍照後檢測:
二、Android以JNI調OpenCV的另外一種配置方法
Application.mk檔案同上。Android.mk檔案例如以下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=SHARE
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include D:\ProgramFile\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ProcessImg
LOCAL_SRC_FILES := DetectFace_JNI.cpp \
src/copyToAssets.cpp \
src/detectFace.cpp
LOCAL_LDLIBS := -lm -llog
OpenCV4Android釋疑: 透析Android以JNI調OpenCV的三種方式(讓OpenCVManager永不困擾)