Refreshed OpenCL sample for Android.

pull/24639/head
Alexander Smorkalov 1 year ago
parent 81656597e9
commit 7f3b6c177f
  1. 12
      samples/android/tutorial-4-opencl/CMakeLists.txt
  2. 2
      samples/android/tutorial-4-opencl/build.gradle.in
  3. 32
      samples/android/tutorial-4-opencl/jni/CLprocessor.cpp
  4. 8
      samples/android/tutorial-4-opencl/jni/CLprocessor.hpp
  5. 17
      samples/android/tutorial-4-opencl/jni/CMakeLists.txt
  6. 20
      samples/android/tutorial-4-opencl/jni/jni.c
  7. 36
      samples/android/tutorial-4-opencl/jni/jni.cpp
  8. 9
      samples/android/tutorial-4-opencl/res/menu/menu.xml
  9. 3
      samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java
  10. 1
      samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java
  11. 80
      samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java

@ -1,12 +1,4 @@
set(sample example-tutorial-4-opencl) set(sample example-tutorial-4-opencl)
if(NOT DEFINED ANDROID_OPENCL_SDK)
message(STATUS "Sample ${sample} is disabled, because ANDROID_OPENCL_SDK is not specified")
return()
endif()
if(ANDROID_NATIVE_API_LEVEL LESS 14)
message(STATUS "Sample ${sample} is disabled, because ANDROID_NATIVE_API_LEVEL < 14")
return()
endif()
if(BUILD_FAT_JAVA_LIB) if(BUILD_FAT_JAVA_LIB)
set(native_deps opencv_java) set(native_deps opencv_java)
@ -14,12 +6,10 @@ else()
set(native_deps opencv_imgproc) set(native_deps opencv_imgproc)
endif() endif()
include_directories(${ANDROID_OPENCL_SDK}/include)
link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_NDK_ABI_NAME})
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}"
LIBRARY_DEPS "${OPENCV_ANDROID_LIB_DIR}" LIBRARY_DEPS "${OPENCV_ANDROID_LIB_DIR}"
SDK_TARGET 21 "${ANDROID_SDK_TARGET}" SDK_TARGET 21 "${ANDROID_SDK_TARGET}"
NATIVE_DEPS ${native_deps} -lGLESv2 -lEGL -lOpenCL NATIVE_DEPS ${native_deps} -lGLESv2 -lEGL
COPY_LIBS YES COPY_LIBS YES
) )
if(TARGET ${sample}) if(TARGET ${sample})

@ -53,8 +53,10 @@ android {
dependencies { dependencies {
//implementation fileTree(dir: 'libs', include: ['*.jar']) //implementation fileTree(dir: 'libs', include: ['*.jar'])
if (gradle.opencv_source == "sdk_path") { if (gradle.opencv_source == "sdk_path") {
println 'Using OpenCV from SDK'
implementation project(':opencv') implementation project(':opencv')
} else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") {
println 'Using OpenCV from Maven repo'
implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@'
} }
} }

@ -1,6 +1,8 @@
#ifdef OPENCL_FOUND
#define __CL_ENABLE_EXCEPTIONS #define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS /*let's give a chance for OpenCL 1.1 devices*/ #define CL_USE_DEPRECATED_OPENCL_1_1_APIS /*let's give a chance for OpenCL 1.1 devices*/
#include <CL/cl.hpp> #include <CL/cl.hpp>
#endif
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <EGL/egl.h> #include <EGL/egl.h>
@ -10,7 +12,9 @@
#include <opencv2/core/ocl.hpp> #include <opencv2/core/ocl.hpp>
#include "common.hpp" #include "common.hpp"
#include "CLprocessor.hpp"
#ifdef OPENCL_FOUND
const char oclProgB2B[] = "// clBuffer to clBuffer"; const char oclProgB2B[] = "// clBuffer to clBuffer";
const char oclProgI2B[] = "// clImage to clBuffer"; const char oclProgI2B[] = "// clImage to clBuffer";
const char oclProgI2I[] = \ const char oclProgI2I[] = \
@ -33,7 +37,7 @@ const char oclProgI2I[] = \
" write_imagef(imgOut, pos, sum*10); \n" \ " write_imagef(imgOut, pos, sum*10); \n" \
"} \n"; "} \n";
void dumpCLinfo() static void dumpCLinfo()
{ {
LOGD("*** OpenCL info ***"); LOGD("*** OpenCL info ***");
try try
@ -83,7 +87,7 @@ cl::CommandQueue theQueue;
cl::Program theProgB2B, theProgI2B, theProgI2I; cl::Program theProgB2B, theProgI2B, theProgI2I;
bool haveOpenCL = false; bool haveOpenCL = false;
extern "C" void initCL() int initCL()
{ {
dumpCLinfo(); dumpCLinfo();
@ -133,20 +137,24 @@ extern "C" void initCL()
catch(const cl::Error& e) catch(const cl::Error& e)
{ {
LOGE("cl::Error: %s (%d)", e.what(), e.err()); LOGE("cl::Error: %s (%d)", e.what(), e.err());
return 1;
} }
catch(const std::exception& e) catch(const std::exception& e)
{ {
LOGE("std::exception: %s", e.what()); LOGE("std::exception: %s", e.what());
return 2;
} }
catch(...) catch(...)
{ {
LOGE( "OpenCL info: unknown error while initializing OpenCL stuff" ); LOGE( "OpenCL info: unknown error while initializing OpenCL stuff" );
return 3;
} }
LOGD("initCL completed"); LOGD("initCL completed");
}
extern "C" void closeCL() if (haveOpenCL)
{ return 0;
else
return 4;
} }
#define GL_TEXTURE_2D 0x0DE1 #define GL_TEXTURE_2D 0x0DE1
@ -230,6 +238,16 @@ void procOCL_OCV(int texIn, int texOut, int w, int h)
cv::ocl::finish(); cv::ocl::finish();
LOGD("uploading results to texture costs %d ms", getTimeInterval(t)); LOGD("uploading results to texture costs %d ms", getTimeInterval(t));
} }
#else
int initCL()
{
return 5;
}
#endif
void closeCL()
{
}
void drawFrameProcCPU(int w, int h, int texOut) void drawFrameProcCPU(int w, int h, int texOut)
{ {
@ -263,7 +281,7 @@ void drawFrameProcCPU(int w, int h, int texOut)
enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3}; enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3};
extern "C" void processFrame(int tex1, int tex2, int w, int h, int mode) void processFrame(int tex1, int tex2, int w, int h, int mode)
{ {
switch(mode) switch(mode)
{ {
@ -271,12 +289,14 @@ extern "C" void processFrame(int tex1, int tex2, int w, int h, int mode)
case PROC_MODE_CPU: case PROC_MODE_CPU:
drawFrameProcCPU(w, h, tex2); drawFrameProcCPU(w, h, tex2);
break; break;
#ifdef OPENCL_FOUND
case PROC_MODE_OCL_DIRECT: case PROC_MODE_OCL_DIRECT:
procOCL_I2I(tex1, tex2, w, h); procOCL_I2I(tex1, tex2, w, h);
break; break;
case PROC_MODE_OCL_OCV: case PROC_MODE_OCL_OCV:
procOCL_OCV(tex1, tex2, w, h); procOCL_OCV(tex1, tex2, w, h);
break; break;
#endif
default: default:
LOGE("Unexpected processing mode: %d", mode); LOGE("Unexpected processing mode: %d", mode);
} }

@ -0,0 +1,8 @@
#ifndef __CL_PROCESSOR_HPP__
#define __CL_PROCESSOR_HPP__
int initCL();
void closeCL();
void processFrame(int tex1, int tex2, int w, int h, int mode);
#endif

@ -4,17 +4,32 @@ set(target JNIpart)
project(${target} CXX) project(${target} CXX)
if (OPENCV_FROM_SDK) if (OPENCV_FROM_SDK)
message(STATUS "Using OpenCV from local SDK")
set(ANDROID_OPENCV_COMPONENTS "opencv_java" CACHE STRING "") set(ANDROID_OPENCV_COMPONENTS "opencv_java" CACHE STRING "")
else() else()
message(STATUS "Using OpenCV from AAR (Maven repo)")
set(ANDROID_OPENCV_COMPONENTS "OpenCV::opencv_java${OPENCV_VERSION_MAJOR}" CACHE STRING "") set(ANDROID_OPENCV_COMPONENTS "OpenCV::opencv_java${OPENCV_VERSION_MAJOR}" CACHE STRING "")
endif() endif()
message(STATUS "ANDROID_ABI=${ANDROID_ABI}") message(STATUS "ANDROID_ABI=${ANDROID_ABI}")
find_package(OpenCV REQUIRED COMPONENTS ${ANDROID_OPENCV_COMPONENTS}) find_package(OpenCV REQUIRED COMPONENTS ${ANDROID_OPENCV_COMPONENTS})
find_package(OpenCL QUIET)
file(GLOB srcs *.cpp *.c) file(GLOB srcs *.cpp *.c)
file(GLOB hdrs *.hpp *.h) file(GLOB hdrs *.hpp *.h)
include_directories("${CMAKE_CURRENT_LIST_DIR}") include_directories("${CMAKE_CURRENT_LIST_DIR}")
add_library(${target} SHARED ${srcs} ${hdrs}) add_library(${target} SHARED ${srcs} ${hdrs})
target_link_libraries(${target} ${ANDROID_OPENCV_COMPONENTS} -lGLESv2 -lEGL -lOpenCL)
target_link_libraries(${target} ${ANDROID_OPENCV_COMPONENTS} -lGLESv2 -lEGL -llog)
if(OpenCL_FOUND)
include_directories(${OpenCL_INCLUDE_DIRS})
target_link_libraries(${OpenCL_LIBRARIES})
add_definitions("-DOPENCL_FOUND")
elseif(DEFINED ANDROID_OPENCL_SDK)
include_directories(${ANDROID_OPENCL_SDK}/include)
link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_NDK_ABI_NAME})
target_link_libraries(-lOpenCL)
add_definitions("-DOPENCL_FOUND")
endif()

@ -1,20 +0,0 @@
#include <jni.h>
int initCL();
void closeCL();
void processFrame(int tex1, int tex2, int w, int h, int mode);
JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativePart_initCL(JNIEnv * env, jclass cls)
{
return initCL();
}
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_closeCL(JNIEnv * env, jclass cls)
{
closeCL();
}
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_processFrame(JNIEnv * env, jclass cls, jint tex1, jint tex2, jint w, jint h, jint mode)
{
processFrame(tex1, tex2, w, h, mode);
}

@ -0,0 +1,36 @@
#include <jni.h>
#include "CLprocessor.hpp"
extern "C" {
JNIEXPORT jboolean JNICALL Java_org_opencv_samples_tutorial4_NativePart_builtWithOpenCL(JNIEnv * env, jclass cls);
JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativePart_initCL(JNIEnv * env, jclass cls);
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_closeCL(JNIEnv * env, jclass cls);
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_processFrame(JNIEnv * env, jclass cls, jint tex1, jint tex2, jint w, jint h, jint mode);
JNIEXPORT jboolean JNICALL Java_org_opencv_samples_tutorial4_NativePart_builtWithOpenCL(JNIEnv * env, jclass cls)
{
#ifdef OPENCL_FOUND
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativePart_initCL(JNIEnv * env, jclass cls)
{
return initCL();
}
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_closeCL(JNIEnv * env, jclass cls)
{
closeCL();
}
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_processFrame(JNIEnv * env, jclass cls, jint tex1, jint tex2, jint w, jint h, jint mode)
{
processFrame(tex1, tex2, w, h, mode);
}
} // extern "C"

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<group android:checkableBehavior="single">
<item android:id="@+id/no_proc" android:title="No processing" />
<item android:id="@+id/cpu" android:title="Use CPU code" />
<item android:id="@+id/ocl_direct" android:title="Use OpenCL direct" />
<item android:id="@+id/ocl_ocv" android:title="Use OpenCL via OpenCV" />
</group>
</menu>

@ -65,7 +65,8 @@ public class MyGLSurfaceView extends CameraGLSurfaceView implements CameraGLSurf
Toast.makeText(getContext(), "onCameraViewStarted", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "onCameraViewStarted", Toast.LENGTH_SHORT).show();
} }
}); });
NativePart.initCL(); if (NativePart.builtWithOpenCL())
NativePart.initCL();
frameCounter = 0; frameCounter = 0;
lastNanoTime = System.nanoTime(); lastNanoTime = System.nanoTime();
} }

@ -12,6 +12,7 @@ public class NativePart {
public static final int PROCESSING_MODE_OCL_DIRECT = 2; public static final int PROCESSING_MODE_OCL_DIRECT = 2;
public static final int PROCESSING_MODE_OCL_OCV = 3; public static final int PROCESSING_MODE_OCL_OCV = 3;
public static native boolean builtWithOpenCL();
public static native int initCL(); public static native int initCL();
public static native void closeCL(); public static native void closeCL();
public static native void processFrame(int tex1, int tex2, int w, int h, int mode); public static native void processFrame(int tex1, int tex2, int w, int h, int mode);

@ -1,6 +1,5 @@
package org.opencv.samples.tutorial4; package org.opencv.samples.tutorial4;
import android.app.Activity;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
@ -10,11 +9,20 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
public class Tutorial4Activity extends Activity { import org.opencv.android.CameraActivity;
public class Tutorial4Activity extends CameraActivity {
private MyGLSurfaceView mView; private MyGLSurfaceView mView;
private TextView mProcMode; private TextView mProcMode;
private boolean builtWithOpenCL = false;
private MenuItem mItemNoProc;
private MenuItem mItemCpu;
private MenuItem mItemOclDirect;
private MenuItem mItemOclOpenCV;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -38,6 +46,7 @@ public class Tutorial4Activity extends Activity {
} }
}); });
builtWithOpenCL = NativePart.builtWithOpenCL();
mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING);
} }
@ -55,48 +64,37 @@ public class Tutorial4Activity extends Activity {
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); mItemNoProc = menu.add("No processing");
inflater.inflate(R.menu.menu, menu); mItemCpu = menu.add("Use CPU code");
return super.onCreateOptionsMenu(menu); if (builtWithOpenCL) {
mItemOclOpenCV = menu.add("Use OpenCL via OpenCV");
mItemOclDirect = menu.add("Use OpenCL direct");
}
return true;
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { String procName = "Not selected";
case R.id.no_proc: int procMode = NativePart.PROCESSING_MODE_NO_PROCESSING;
runOnUiThread(new Runnable() {
public void run() { if (item == mItemNoProc) {
mProcMode.setText("Processing mode: No Processing"); procMode = NativePart.PROCESSING_MODE_NO_PROCESSING;
} procName = "Processing mode: No Processing";
}); } else if (item == mItemCpu) {
mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); procMode = NativePart.PROCESSING_MODE_CPU;
return true; procName = "Processing mode: CPU";
case R.id.cpu: } else if (item == mItemOclOpenCV && builtWithOpenCL) {
runOnUiThread(new Runnable() { procMode = NativePart.PROCESSING_MODE_OCL_OCV;
public void run() { procName = "Processing mode: OpenCL via OpenCV (TAPI)";
mProcMode.setText("Processing mode: CPU"); } else if (item == mItemOclDirect && builtWithOpenCL) {
} procMode = NativePart.PROCESSING_MODE_OCL_DIRECT;
}); procName = "Processing mode: OpenCL direct";
mView.setProcessingMode(NativePart.PROCESSING_MODE_CPU);
return true;
case R.id.ocl_direct:
runOnUiThread(new Runnable() {
public void run() {
mProcMode.setText("Processing mode: OpenCL direct");
}
});
mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_DIRECT);
return true;
case R.id.ocl_ocv:
runOnUiThread(new Runnable() {
public void run() {
mProcMode.setText("Processing mode: OpenCL via OpenCV (TAPI)");
}
});
mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_OCV);
return true;
default:
return false;
} }
mView.setProcessingMode(procMode);
mProcMode.setText(procName);
return true;
} }
} }

Loading…
Cancel
Save