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

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

我有一个 android 应用程序,我想对来自 android Camera2 API 的实时图像进行 运行 一些 OpenCV 图像处理.目前,如果我不做任何处理,我可以在 OnImageAvailble 函数中以 30 fps 的速度接收常规 1280x720 帧的图像。

现在作为一个肮脏的 hack,我请求来自 ImageReader 的 JPEG 格式的图像,然后将位图传递给 jni,这大大降低了性能。

将 YUV 帧传递给 cv Mat 对象中的 jni 的最有效方法是什么。另外,我想将此帧转换为 RGB 以进行进一步处理。我应该更改 Java 端的格式还是应该将 Mat 对象传递给 jni 并仅在那里转换色彩空间。

由于显而易见的原因,您在 C++ 中所做的任何事情都比 Java 等效方法快得多,包括 YUV 到 RGB 转换(即使 Java 实现依赖于编译库)。[​​=13= ]

您可以通过 JNI 将 java 中现有 Mat 中的指针直接传递给 C++。假设我想使用 C++ 和 JNI 执行 Canny(),并且我有一个这样定义的 JNI 函数:

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

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

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

此函数在 C++ 中的实现将以与此类似的方式接收此指针(如果这不起作用,请将 long 替换为 jlong​​):

// 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 中,毕竟它是一个指针,所以我们从来没有复制过。

据我所知,这已经是最快的速度了。

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

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

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat