我的Opencv4Android添加V4L2支持的移植记录(4)

来源:互联网 发布:java安全阻止怎么解除 编辑:程序博客网 时间:2024/05/22 13:26

博主QQ:1356438802


这次我们来对《我的Opencv4Android添加V4L2支持的移植记录(2)》的实时预览进行一些优化。


先来看那篇文章中源码的ImageProc.cpp文件

#include "ImageProc.h"#include "cv.h"#include "highgui.h"#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include <string>#include <vector>using namespace cv;using namespace std;#ifdef __cplusplusextern "C" {#pragma message("------------------------ ImageProc.cpp")#endifCvCapture *pCapture = NULL;IplImage *frame = NULL;int id;JNIEXPORT jintArray JNICALL Java_luo_uvc_jni_ImageProc_grayProc(JNIEnv* env,jclass obj, jintArray buf, jint w, jint h){jint *cbuf;cbuf = env->GetIntArrayElements(buf, false);if (cbuf == NULL){return 0;}Mat imgData(h, w, CV_8UC4, (unsigned char*) cbuf);uchar* ptr = imgData.ptr(0);for (int i = 0; i < w * h; i++){//计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B//对于一个int四字节,其彩色值存储方式为:BGRAint grayScale = (int) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587+ ptr[4 * i + 0] * 0.114);ptr[4 * i + 1] = grayScale;ptr[4 * i + 2] = grayScale;ptr[4 * i + 0] = grayScale;}int size = w * h;jintArray result = env->NewIntArray(size);env->SetIntArrayRegion(result, 0, size, cbuf);env->ReleaseIntArrayElements(buf, cbuf, 0);return result;}JNIEXPORT jint JNICALL Java_luo_uvc_jni_ImageProc_connectCamera(JNIEnv* env,jclass obj, jint device){id = device;pCapture = NULL;LOGI("usb camera id=%d Java_luo_uvc_jni_ImageProc_connectCamera start ....\n", id);//查找UVC设备pCapture = cvCaptureFromCAM(id);if (NULL != pCapture){LOGE("usb camera open success!\n");return 0;}LOGI("usb camera Java_luo_uvc_jni_ImageProc_connectCamera end ....\n");return -1;}JNIEXPORT jint JNICALL Java_luo_uvc_jni_ImageProc_releaseCamera(JNIEnv* env,jclass obj){LOGI("usb camera Java_luo_uvc_jni_ImageProc_releaseCamera start ....\n");if (NULL != pCapture){cvReleaseCapture(&pCapture);pCapture = NULL;}LOGI("usb camera Java_luo_uvc_jni_ImageProc_releaseCamera end ....\n");return 0;}struct FrameInfoClass{    jfieldID width;    jfieldID heigth;    jfieldID imageSize;    jfieldID pixels;};JNIEXPORT jobject JNICALL Java_luo_uvc_jni_ImageProc_getFrame(JNIEnv* _env,jclass obj){LOGI("------------Java_luo_uvc_jni_ImageProc_getFrame\n");if(NULL != pCapture){LOGI("------------start cvQueryFrame\n");frame = NULL;frame = cvQueryFrame(pCapture); //取图片帧if(NULL == frame){LOGE("cvQueryFrame(capture) failed!!!!!!!!!!!!!!!!!!!!!!!");return NULL;}struct FrameInfoClass frameInfoClass;//内部类用$//luo/uvc/jni/ImageProc$FrameInfojclass class2 = _env->FindClass("luo/uvc/jni/ImageProc$FrameInfo");LOGI("1=GetFieldID\n");frameInfoClass.width = _env->GetFieldID(class2, "mWidth", "I");LOGI("2=GetFieldID\n");frameInfoClass.heigth = _env->GetFieldID(class2, "mHeight", "I");LOGI("3=GetFieldID\n");frameInfoClass.imageSize = _env->GetFieldID(class2, "mImageSize", "I");LOGI("4=GetFieldID\n");frameInfoClass.pixels = _env->GetFieldID(class2, "mPixels", "[I");LOGI("5=GetFieldID\n");//jobject joFrame = _env->AllocObject(class2);LOGI("6=GetFieldID\n");LOGI("frame->width = %d\n", frame->width);LOGI("frame->height = %d\n", frame->height);LOGI("frame->imageSize = %d\n", frame->imageSize);_env->SetIntField(joFrame, frameInfoClass.width, frame->width);_env->SetIntField(joFrame, frameInfoClass.heigth, frame->height);_env->SetIntField(joFrame, frameInfoClass.imageSize, frame->imageSize);int size = frame->width * frame->height;//创建一个新的java数组(jarray),但是jarray不是C数组类型,不能直接访问jarrayjintArray jiArr = _env->NewIntArray(size);jint *ji;#if 1   //可用LOGI("7=GetFieldID\n");//RGB --> ARGB8888Mat frameRGB(frame->height, frame->width, CV_8UC3, frame->imageData), frameARGB;cvtColor(frameRGB, frameARGB, CV_RGB2RGBA);//JNI支持一系列的Get/Release<Type>ArrayElement 函数,允许本地代码获取一个指向基本C类型数组的元素的指针。ji = _env->GetIntArrayElements(jiArr, 0);memcpy((jbyte *)ji, frameARGB.data, 4 * size);_env->ReleaseIntArrayElements(jiArr, ji, 0); //可加,可不加_env->SetObjectField(joFrame, frameInfoClass.pixels, jiArr);LOGI("8=GetFieldID\n");#else   //可用//可以使用GetIntArrayRegion函数来把一个 int数组中的所有元素复制到一个C缓冲区中//SetIntArrayRegion则是逆过程LOGI("13=GetFieldID\n");_env->SetIntArrayRegion(jiArr, 0, 2, abc);_env->SetObjectField(joFrame, company_class.money, jiArr);#endifLOGI("Java_luo_uvc_jni_ImageProc_getFrame end\n");return joFrame;}LOGI("=================Java_luo_uvc_jni_ImageProc_getFrame failed\n");return 0;}JNIEXPORT jint JNICALL Java_luo_uvc_jni_ImageProc_getWidth(JNIEnv* env,jclass obj){return 0;}JNIEXPORT jint JNICALL Java_luo_uvc_jni_ImageProc_getHeight(JNIEnv* env,jclass obj){return 0;}#ifdef __cplusplus}#endif/* end of extern */

其中Java_luo_uvc_jni_ImageProc_getFrame这个函数是提取图像,给SurfaceView刷新显示的,由于它整个流程操作数据块比较多,而且在JNI层构造了一个FrameInfo对象,效率很低。我们对其进行改造。

void Java_luo_uvc_jni_ImageProc_getFrame(JNIEnv* env, jobject thiz,jobject bitmap){AndroidBitmapInfo info;void *pixels;char *pixel;int ret;int width = 0;int height = 0;int ImageSize = 0;if (NULL != pCapture){//1. get frameLOGI("------------start cvQueryFrame\n");frame = NULL;frame = cvQueryFrame(pCapture);if (NULL == frame){LOGE("cvQueryFrame(capture) failed!!!!!!!!!!!!!!!!!!!!!!!");return;}if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0){LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);return;}width = info.width;height = info.height;ImageSize = width * height;LOGI("------------info.width=%d, info.height=%d\n", info.width,info.height);if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888){LOGE("Bitmap format is not RGBA_8888 !");return;}if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0){LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);return;}pixel = (char *)pixels;for (int i = 0; i < ImageSize; i++){//需要注意的是对于ARGB_8888类型的图像而言,其每一个像素值在int型数据中的存储序列为BGRA。*(pixel + 4 * i + 0) = *(frame->imageData + 3 * i + 2);*(pixel + 4 * i + 1) = *(frame->imageData + 3 * i + 1);*(pixel + 4 * i + 2) = *(frame->imageData + 3 * i + 0);*(pixel + 4 * i + 3) = 0xFF;}AndroidBitmap_unlockPixels(env, bitmap);}}

其实就是取java层的Bitmap对象的data空间,直接把frame-->imageData拷贝过去。特别注意这里的RGB-->ARGB_8888格式转换方式,上面是用MAT矩阵转换,而我这里采取直接复制的方式,本质是一样的。对于ARGB_8888类型的图像而言,其每一个像素值在int型数据中的存储序列为BGRA。


经过这样的修改后,预览的实时性有很大的提高!


示例下载:http://download.csdn.net/detail/luoyouren/9594703













0 0
原创粉丝点击