標籤:
OpenCV Android SDK中提供的靜態、動態庫是不支援OpenCL加速的,如果在程式中調用OpenCL相關函數,編譯時間不會報錯,但運行時logcat會輸出如下資訊,提示OpenCL函數不可用
08-11 11:43:07.140: E/cv::error()(18198): OpenCV Error: Unknown error code -6 (OpenCL function is not available: [clGetPlatformIDs]) in void* opencl_check_fn(int), file /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/ocl/src/cl_runtime/cl_runtime.cpp, line 8308-11 11:43:07.140: E/cv::error()(18198): OpenCV Error: Unknown error code -221 (OpenCL not available) in static cv::ocl::ContextImpl* cv::ocl::ContextImpl::getContext(), file /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/ocl/src/cl_context.cpp, line 678
所以,如果想使用OpenCV for Android中的ocl模組,需要自己編譯一套支援OpenCL的OpenCV庫檔案,同時還需要有一部具有OpenCL驅動的裝置。下面詳細講述整個過程,整個的編譯過程都是基於windows平台的,其他平台過程類似,只是編譯時間的命令會有所不同。
1.如何判斷裝置是否支援OpenCL
可以下載一款叫OpenCL-Z的軟體。安裝後,它可以檢測當前裝置的GPU是否支援OpenCL和是否具有OpenCL驅動。下面是豌豆莢上的:
http://www.wandoujia.com/apps/com.robertwgh.opencl_z_android
2.編譯帶OpenCL模組的OpenCV for Android
(1)首先需要從OpenCV官網下載源碼,我是基於2.4.11版本的源碼編譯的(3.x版本工程整體結構變化太大,而且單獨的ocl模組被合入其他模組了,我還沒搞明白怎麼用)。
這個網址可以下載到2.4.11版本的源碼:https://github.com/Itseez/opencv/releases
(2)接下來配置需要的工具,主要有兩個:cmake,Android ndk。下載&安裝,在環境變數中配置好cmake的bin目錄,並將ndk的根目錄添加為ANDROID_NDK值。
(3)在opencv_path\modules\ocl\src\cl_runtime\cl_runtime.cpp檔案中,做如下修改:
第48行,#if defined(__linux__) 改為 #if defined(__linux__)&&!defined(__ANDROID__)
第70行後,添加如下代碼:
#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" };#endifstatic 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
(4)編譯opencv。開啟cmd,將目前的目錄切換到opencv_path\platforms\下面,執行如下命令:
1 mkdir build_opencl2 cd build_opencl3 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_ABI=armeabi ..\..
其中,ANDROID_NDK是在環境變數中設定好的變數值,為android ndk的根目錄,DANDROID_ABI可以根據需要選擇。執行完畢後,執行如下命令即可:
cmake --build .
注意build後面的那個“.”不能少。
(5)編譯完成後,把\build_opencl\lib\armeabi下面的庫覆蓋到opencv android sdk中的sdk\native\libs目錄下對應的檔案夾。
(6)clean原有的工程,然後build project。在裝置上運行,一切OK。
這裡是測試工程的源碼,需要用自己圖片path替換代碼中的path,然後app會在同一目錄下產生一幅灰階圖。例如:輸入映像為裝置根目錄下a.jpg,運行後同一目錄下會產生agray.jpg灰階圖片。
編譯並使用帶有OpenCL模組的OpenCV for android SDK