利用OPENCV为android相机开发图像处理库

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 <jni.h>
/* 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 <stdio.h>
#include <jni.h>
#include<Android/log.h>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

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;
    }

}

编写MK文件,Application.mk,为了兼容性,参数使用 ALL,生成所有支持的CPU的库

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)


注意路径,由于是使用OPENCV开发,对OPENCV有依赖,编译时需要OPENCV路径,我的OPENCV的SDK路径在C盘,需要改成自己的

ndk-build生成相应libImageProc.so库在项目中使用.

ImageProc.convertRGBA(previewSizeWidth, previewSizeHeight, mData, pixels);



猜你喜欢

转载自blog.csdn.net/blogercn/article/details/78024872