android调用opencv的方法有三种,利于OPENCVSDK manager调用,这种方法最简单,不过需要安装客户端,相对来说,很多适合都是不适用的。一种是使用OPENCV提供的JAVA库加SO库调用,这种方法相当来说,省掉了多安装一个APP的负责,更有利于软件推广。最后一种是利于JNI调用OPENV的C/C+语言库完成相关功能模块开发,并给JAVA层提供相应的调用接口,这种方式个人感觉效率最高。
使用OPENCV开发相机,一般是借且三种方式,一种是camera的previcewcallback接口提供的预览回调,一种是使用camera2的 ImageReader接口,还有一种使用OPENGL的shader开发相应接口,一旦加了特殊处理,都会产生丢帧。
从相机获取的数据都是YUV格式的BYTE数组,在opencv中先把其转为RGB数组,再对其做畸变,美颜,人脸查找,应用分割或者其他滤镜等技术。
先创建JAVA调用,这里写两个函数,一个YUV转为灰度,一个YUV转为RGBA,文件名字ImageProc,包名myopencv
package myopencv;
public class ImageProc {
static {
System.loadLibrary("ImageProc");
}
public static native boolean convertGray(int width, int height, byte[] NV21FrameData, int[] pixels);
public static native boolean convertRGBA(int width, int height, byte[] yuv, int[] pixels);
}
调用JAVAH生成头文件,头文件不是必需的,如果熟了,可以直接CPP文件
javah -classpath F:\luna5\mycam\bin\classes\ -jni myopencv.ImageProc
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class myopencv_ImageProc */
#ifndef _Included_myopencv_ImageProc
#define _Included_myopencv_ImageProc
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: myopencv_ImageProc
* Method: convertGray
* Signature: (II[B[I)Z
*/
JNIEXPORT jboolean JNICALL Java_myopencv_ImageProc_convertGray
(JNIEnv *, jclass, jint, jint, jbyteArray, jintArray);
/*
* Class: myopencv_ImageProc
* Method: convertRGBA
* Signature: (II[B[I)Z
*/
JNIEXPORT jboolean JNICALL Java_myopencv_ImageProc_convertRGBA
(JNIEnv *, jclass, jint, jint, jbyteArray, jintArray);
#ifdef __cplusplus
}
#endif
#endif
使用opencv编写相应的功能代码
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
#define TAG "Camera XXXXX" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) // 定义LOGD类型
extern "C"
{
jboolean Java_myopencv_ImageProc_convertGray(
JNIEnv* env, jobject thiz, jint width, jint height,
jbyteArray NV21FrameData, jintArray outPixels)
{
jbyte * pNV21FrameData = env->GetByteArrayElements(NV21FrameData, 0);
jint * poutPixels = env->GetIntArrayElements(outPixels, 0);
Mat mNV(height, width, CV_8UC1, (unsigned char*)pNV21FrameData);
Mat mBgra(height, width, CV_8UC4, (unsigned char*) poutPixels);
cvtColor(mNV, mBgra, CV_GRAY2RGBA);
env->ReleaseByteArrayElements(NV21FrameData, pNV21FrameData, 0);
env->ReleaseIntArrayElements(outPixels, poutPixels, 0);
return true;
}
jboolean Java_myopencv_ImageProc_convertRGBA(
JNIEnv *env, jobject thiz, jint width, jint height, jbyteArray yuv, jintArray outPixels)
{
jbyte * pBuf = (jbyte*)env->GetByteArrayElements(yuv, 0);
jint * poutPixels = env->GetIntArrayElements(outPixels, 0);
Mat image(height + height/2, width, CV_8UC1, (unsigned char *)pBuf);
Mat mBgra(height, width, CV_8UC4, (unsigned char*) poutPixels);
cvtColor(image, mBgra, CV_YUV420sp2RGBA);
LOGD("jiaXXX %X", poutPixels[0]);
env->ReleaseByteArrayElements(yuv, pBuf, 0);
env->ReleaseIntArrayElements(outPixels, poutPixels, 0);
return true;
}
jboolean Java_myopencv_ImageProc_convertBeauty(
JNIEnv *env, jobject thiz, jint width, jint height, jbyteArray yuv, jintArray outPixels)
{
return true;
}
jboolean Java_myopencv_ImageProc_convertBackBlur(
JNIEnv *env, jobject thiz, jint width, jint height, jbyteArray yuv, jintArray outPixels)
{
return true;
}
}
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
APP_PLATFORM := android-8
编写Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE:=STATIC
OPENCV_INSTALL_MODULES:=on
include C:/Users/jiazhiguo/Downloads/opencv/sources/samples/android/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := ImageProc
LOCAL_SRC_FILES := ImageProc.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
ndk-build生成相应libImageProc.so库在项目中使用.
ImageProc.convertRGBA(previewSizeWidth, previewSizeHeight, mData, pixels);