简体   繁体   English

在YUV_420_888中将图像从Android发送到OpenCV Mat中的JNI的最有效方式

[英]Most Efficient way to send Image in YUV_420_888 from Android to JNI in OpenCV Mat

I have an android application where I want to run some OpenCV image processing on live images from android Camera2 API. 我有一个Android应用程序,我想在Android Camera2 API的实时图像上运行一些OpenCV图像处理。 Currently, If I don't do any processing, I am able to receive images in OnImageAvailble function at 30 fps for a regular 1280x720 frame. 目前,如果我不进行任何处理,我能够以30 fps的速度接收常规1280x720帧的OnImageAvailble功能。

Now as a dirty hack I am requesting Images from ImageReader in JPEG format and then passing the Bitmap to jni which brings down the performance a lot. 现在作为一个肮脏的黑客,我从ImageReader请求JPEG格式的图像,然后将位图传递给jni ,这会降低性能。

What's the most efficient way to pass the YUV frame to jni in cv Mat object. 什么是在cv Mat对象中将YUV帧传递给jni的最有效方法。 Also, I want to convert this frame to RGB for further processing. 另外,我想将此帧转换为RGB以进行进一步处理。 Should I change the format on Java side or should I pass the Mat object to jni and convert the colorspace there only. 我应该更改Java端的格式,还是应该将Mat对象传递给jni并仅转换颜色空间。

Anything you do in C++ is much faster than the Java equivalent for obvious reasons, including YUV to RGB transformations (even if the Java implementation relies on compiled libraries). 由于显而易见的原因,你在C ++中所做的任何事情都比Java等同得多,包括YUV到RGB的转换(即使Java实现依赖于编译库)。

You can directly pass a pointer from your existing Mat in java directly to C++ through JNI. 您可以直接将指针从Java中现有的Mat直接传递给C ++到JNI。 Supposing I want to do Canny() using C++ and JNI, and I have a JNI function defined like this: 假设我想使用C ++和JNI做Canny(),我有一个像这样定义的JNI函数:

// In Java
public static native boolean nativeCanny(long iAddr);

Notice the long iAddr parameter, that's a direct pointer to my Mat in Java. 注意long iAddr参数,它是指向Java中Mat的直接指针。 You invoke it like this: 你这样调用它:

// In Java
nativeCanny(myImage.getNativeObjAddr());

The implementation of this function in C++ would receive this pointer in a similar way to this (replace long with jlong if this doesn't work): 在C ++中实现此函数将以与此类似的方式接收此指针(如果这不起作用,则用jlong​​替换long):

// In C++
JNIEXPORT jboolean JNICALL
VeryLongName_nativeCanny(JNIEnv *env, jobject instance, long iAddr) {
    cv::Mat* img = (cv::Mat*) iAddr;
    cv::Canny(*img, *img, 80, 100, 3);
    return true;
}

And whatever I did to the img Mat, happens in the java myImage Mat as well, after all it's a pointer so we never made a copy. 无论我对img Mat做了什么,也发生在java myImage Mat中,毕竟它是一个指针,所以我们从来没有复制过。

As far as I know, that's as fast as it gets. 据我所知,这是最快的。

Maybe helpful to you: Since we do a lot of image processing we wrote a library for that purpose in our company. 也许对您有所帮助:由于我们进行了大量的图像处理,因此我们在公司为此目的编写了一个库。 It's not written in C but it's quite performant. 它不是用C语言编写的,而是非常高效的。 After the conversion, you can simply pass the Mat pointer down to your C code via JNI. 转换后,您只需通过JNI将Mat指针传递给C代码即可。

It converts YUVs (Standard Android Camera Format YUV_420_888) to RGB Mats. 它将YUV(标准Android相机格式YUV_420_888)转换为RGB Mats。 In addition, it also allows efficient clipping of the YUV before the conversion (important for very big images, otherwise you would need to convert the whole image, and clip afterward which is expensive). 此外,它还允许在转换之前有效剪切YUV(对于非常大的图像很重要,否则你需要转换整个图像,然后剪辑这是昂贵的)。 Usage is very simple: 用法很简单:

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat https://github.com/quickbirdstudios/yuvToMat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM