[英]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.