Opencv4Android的OpenCL的测试,使用Opencv的ocl封装库

Opencv3.2.0和Opencv2.4比较,代码目录结构发生了很大的变化,至少它的ocl的封装发生了变化。下面基于Opencv3.2.0进行介绍怎么去使用Opencv的ocl库,当然,本篇文章只做简单的介绍,展示如何获取到Android手机的GPU信息。
我在上一篇文章中也介绍了如何获取GPU信息,《Android OpenCL测试程序,使用dlopen动态加载libOpenCL.so库》,这篇文章纯粹是利用OpenCL自身的方法去获取的,没有通过Opencv的ocl封装库。

下载sources和Android pack:

http://opencv.org/releases.html,不过官网下载速度好慢好慢,我在百度云上共享了一份百度云
这里为什么还要下载sources代码呢,因为如果Opencv4Android包中提供的库不支持OpenCL,我们可以自己编译,我在另一篇文章中介绍到怎么编译,大家可以去参阅:《为Android平台编译支持OpenCL的Opencv静态库》

声明native函数并生成头文件

public class OpenclTest {  

    public void testOpencl(){  
        testopencl();  
    }  
    public native void testopencl();  
}  

进入package同级目录,利用javah命令生成头文件

javah -d ../jni -jni com.pax.imagesobelfilter.OpenclTest

编写openclTest.cpp文件

#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和Application.mk文件

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

运行,查看结果

Opencv4Android的OpenCL的测试,使用Opencv的ocl封装库_第1张图片

demo下载,如果不能运行,请告知,谢谢!

如果获取不到手机的GPU信息,那么有以下两个可能:

  • 没有链接opencv的静态库,需要在Android.mk中指定链接。

  • opencv静态库不支持opencl,需要编译,参照《为Android平台编译支持OpenCL的Opencv静态库》

你可能感兴趣的:(Opencv4Android)