Opencv3.2.0和Opencv2.4比较,代码目录结构发生了很大的变化,至少它的ocl的封装发生了变化。下面基于Opencv3.2.0进行介绍怎么去使用Opencv的ocl库,当然,本篇文章只做简单的介绍,展示如何获取到Android手机的GPU信息。
我在上一篇文章中也介绍了如何获取GPU信息,《Android OpenCL测试程序,使用dlopen动态加载libOpenCL.so库》,这篇文章纯粹是利用OpenCL自身的方法去获取的,没有通过Opencv的ocl封装库。
http://opencv.org/releases.html,不过官网下载速度好慢好慢,我在百度云上共享了一份百度云
这里为什么还要下载sources代码呢,因为如果Opencv4Android包中提供的库不支持OpenCL,我们可以自己编译,我在另一篇文章中介绍到怎么编译,大家可以去参阅:《为Android平台编译支持OpenCL的Opencv静态库》
public class OpenclTest {
public void testOpencl(){
testopencl();
}
public native void testopencl();
}
进入package同级目录,利用javah命令生成头文件
javah -d ../jni -jni com.pax.imagesobelfilter.OpenclTest
#include"com_pax_imagesobelfilter_OpenclTest.h"
#include <android/log.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/ocl.hpp>
#define LOG_TAG "openclTest"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
using namespace cv;
JNIEXPORT void JNICALL Java_com_pax_imagesobelfilter_OpenclTest_testopencl
(JNIEnv *jenv, jobject thiz){
test();
}
void test(){
try {
if (!cv::ocl::haveOpenCL()){
LOGD("OpenCL is not availble");
} else{
LOGD("OpenCL is avaible");
}
if (cv::ocl::useOpenCL()){
LOGD("use OpenCL");
} else{
LOGD("don't use OpenCL");
}
cv::ocl::Context context;
if (!context.create(cv::ocl::Device::TYPE_GPU))
{
LOGD("Failed creating the context...");
return;
}
else
{
LOGD("ocl::Context is OK");
}
LOGD(" %lu GPU devices are detected.",context.ndevices());
for (int i = 0; i < context.ndevices(); i++)
{
cv::ocl::Device device = context.device(i);
LOGD("name: %s",device.name().c_str());
if (device.available()){
LOGD("device is avaible");
} else{
LOGD("devive is not avaible");
}
if (device.imageSupport()){
LOGD("device support image");
} else{
LOGD("device doesn't support image");
}
LOGD("OpenCL_C_Version : %s" ,device.OpenCL_C_Version().c_str());
}
}
catch(cv::Error::Code& e)
{
LOGE("cv::Error::Code %d", e);
}
}
这里只用到几个基本函数,还要其他函数没有引用到,大家可以自己摸索摸索。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_ANDROID_SDK := F:\Android\opencv-3.2.0-android-sdk\OpenCV-android-sdk
OPENCV_LIB_TYPE := STATIC
ifdef OPENCV_ANDROID_SDK
ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")
include ${OPENCV_ANDROID_SDK}/OpenCV.mk
else
include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk
endif
else
include ../../sdk/native/jni/OpenCV.mk
endif
LOCAL_MODULE := ocl
LOCAL_CPPFLAGS += -I$(LOCAL_PATH)
LOCAL_SRC_FILES := openclTest.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
其中,OPENCV_LIB_TYPE := STATIC
,指定链接静态库,如果不指定,无法获取到手机的GPU信息。${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk
,引用了OpenCV.mk,我们找到这个文件,第21行到第34行的内容如下:
OPENCV_MODULES:=face shape stitching objdetect superres videostab calib3d features2d highgui videoio imgcodecs video photo ml imgproc flann core
OPENCV_SUB_MK:=$(call my-dir)/OpenCV-$(TARGET_ARCH_ABI).mk
ifeq ($(OPENCV_LIB_TYPE),)
OPENCV_LIB_TYPE:=SHARED
endif
ifeq ($(OPENCV_LIB_TYPE),SHARED)
OPENCV_LIBS:=java3
OPENCV_LIB_TYPE:=SHARED
else
OPENCV_LIBS:=$(OPENCV_MODULES)
OPENCV_LIB_TYPE:=STATIC
endif
很显然,如果指定了OPENCV_LIB_TYPE=STATIC
,将会引用到 OPENCV_MODULES 指定的静态库。如果指定了OPENCV_LIB_TYPE=SHARE
,需要加载libopencv_java3.so动态库。我这里只链接静态库去测试,大家如果想折腾,可以试下动态库。
Application.mk
APP_CPPFLAGS := -frtti -fexceptions
APP_STL := stlport_static
APP_STL := gnustl_static
APP_ABI := armeabi-v7a arm64-v8a
APP_PLATFORM := android-8
进入jni同级目录,利用ndk-build命令进行编译
ndk-build
demo下载,如果不能运行,请告知,谢谢!
如果获取不到手机的GPU信息,那么有以下两个可能:
没有链接opencv的静态库,需要在Android.mk中指定链接。
opencv静态库不支持opencl,需要编译,参照《为Android平台编译支持OpenCL的Opencv静态库》