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

我有一个Android应用程序,我想在Android API的实时图像上运行一些图像处理。目前,如果我不进行任何处理,我能够以30 fps的速度接收常规帧中的图像。OpenCVCamera2OnImageAvailble1280x720

现在,作为一个肮脏的黑客,我正在以JPEG格式从ImageReader请求图像,然后将位图传递到该位图,这会大大降低性能。jni

将 YUV 帧传递到对象的最有效方法是什么?另外,我想将此帧转换为进一步处理。我应该在Java端更改格式,还是应该将对象传递到并仅在那里转换颜色空间。jnicv MatRGBMatjni


答案 1

出于显而易见的原因,您在C++中执行的任何操作都比Java等效物快得多,包括YUV到RGB的转换(即使Java实现依赖于编译的库)。

您可以通过JNI直接从Java中的现有Mat将指针直接传递给C++。假设我想使用C++和JNI来做Canny(),并且我有一个JNI函数,定义如下:

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

请注意很长的iAddr参数,这是Java中指向我的Mat的直接指针。你像这样调用它:

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

此函数在 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;
}

无论我对img Mat做了什么,在java myImage Mat中也会发生,毕竟它是一个指针,所以我们从来没有做过复制。

据我所知,这是最快的。


答案 2

也许对您有所帮助:由于我们进行了大量的图像处理,因此我们在公司中为此目的编写了一个库。它不是用C语言编写的,但它的性能非常好。转换后,您只需通过JNI将Mat指针向下传递到C代码即可。

它将YUV(标准Android相机格式YUV_420_888)转换为RGB Mats。此外,它还允许在转换之前有效地剪辑YUV(对于非常大的图像很重要,否则您需要转换整个图像,然后剪辑,这很昂贵)。用法非常简单:

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat


推荐