為Android平臺編譯支援OpenCL的Opencv靜態庫
Opencv中封裝了OpenCL,直接下載的Opencv4Android SDK中提供了一些相關的庫,我們可以利用nm命令檢視這些庫是否包含opencl的相關函式。ocl整合在core中,所以我們直接檢視libopencv_core.a這個庫。
nm -D libopencv_core.a
檢視結果如下圖,其中包含了ocl、opencl等.o檔案。
也許,這還不能斷定這個靜態庫是否支援OpenCL,那麼最好的方法就是寫一個測試程式,去嘗試獲取手機的GPU資訊,之後我也會寫一篇文章來介紹Android平臺的GPU資訊獲取。大家可以利用OpenCL-Z這個軟體來檢視手機平臺的GPU資訊。
當然,我們可以親自動手去編譯一套可以支援opencl的庫,本文也基於OpenCV3.2.0,介紹如何編譯Opencl支援庫。
工具準備:
Cmake的安裝和配置 點選下載cmake ,需要指定cmake的系統變數,安裝過程有個選項可以選上,會自動新增Cmake的bin目錄到path變數中。
Android NDK:可以到官網下載或者直接用Android studio安裝,同樣也需要指定NDK的系統變數。
Opencv Sources的下載:官網,百度雲
關鍵檔案修改:
修改CMakeList.txt:
開啟該檔案,找到WITH_OPENCL這一項,將其狀態修改為ON:
修改opencl_core.cpp檔案:
開啟檔案..\modules\core\src\opencl\runtime\opencl_core.cpp,找到 #if defined(linux)這一項將其修改為:
#if defined(__linux__)&&!defined(__ANDROID__)
如下:
#if defined(__linux__)&&!defined(__ANDROID__) #include <dlfcn.h> #include <stdio.h> ...... #endif //linux
在上面這片程式碼塊之後新增Android的編譯程式碼:
#if defined(__ANDROID__) #include <dlfcn.h> #include <sys/stat.h> #if defined(__ARM_ARCH_8A__) || defined(_X64_) static const char *default_so_paths[] = { "/system/lib64/libOpenCL.so", "/system/vendor/lib64/libOpenCL.so", "/system/vendor/lib64/egl/libGLES_mali.so" }; #else static const char *default_so_paths[] = { "/system/lib/libOpenCL.so", "/system/vendor/lib/libOpenCL.so", "/system/vendor/lib/egl/libGLES_mali.so" }; #endif static int access_file(const char *filename) { struct stat buffer; return (stat(filename, &buffer) == 0); } static void* GetProcAddress (const char* name) { static void* h = NULL; unsigned int i; if (!h) { const char* name; for(i=0; i<(sizeof(default_so_paths)/sizeof(char*)); i++) { if(access_file(default_so_paths[i])) { name = (char *)default_so_paths[i]; h = dlopen(name, RTLD_LAZY); if (h) break; } } if (!h) return NULL; } return dlsym(h, name); } #define CV_CL_GET_PROC_ADDRESS(name) GetProcAddress(name) #endif
編譯Opencv
在..\platforms\目錄下建立一個新資料夾opencv_armeabi_v7a並進入該目錄,建立一個opencv_build.bat檔案,檔案裡面的內容如下:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DWITH_EIGEN=off -DCMAKE_TOOLCHAIN_FILE=..\android\android.toolchain.cmake -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows-x86_64\bin\make.exe" -DANDROID_NATIVE_API_LEVEL=23 -DANDROID_ABI=armeabi-v7a ..\..
cmake --build .
上面ANDROID_NDK是Android NDK的home目錄,需要在環境變數中指定好
-DANDROID_NATIVE_API_LEVEL=23: 指定api level為android-23
-DANDROID ABI=armeabi-v7a: 指定編譯的架構為armeabi-v7a, 它可以指定為以下這些:
·”armeabi-v7a”, “armeabi”, “armeabi-v7a with NEON”, “armeabi-v7a-hard with NEON”, “armeabi-v7a with VFPV3”, “armeabi-v6 with VFP”, “arm64-v8a”, “mips”, “mips64”, “x86”, “x86_64”
雙擊opencv_build.bat執行編譯命令,耐心等待,等很久。
編譯完成後,可以在lib目錄下找到編譯好的靜態庫。這時候再利用nm命令去檢視庫中的資訊,就可以知道是否包含有opencl相關的cpp檔案了。當然,大家可以寫一個小demo來驗證這些庫是否支援OpenCL。如何寫一個demo來檢驗一些編譯庫呢,可以參閱:Opencv4Android的OpenCL的測試,使用Opencv的ocl封裝庫