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

Him*_*der 18 java java-native-interface android opencv opencv4android

我有一个Android应用程序,我想OpenCV在Android Camera2API的实时图像上运行一些图像处理.目前,如果我不进行任何处理,我能够以OnImageAvailble30 fps的速度接收常规1280x720帧的图像.

现在作为一个肮脏的黑客,我正在以JPEG格式从ImageReader请求图像,然后传递Bitmap,jni从而大大降低了性能.

什么是对YUV帧传送到最有效的方式jnicv Mat对象.此外,我想将此帧转换RGB为进一步处理.我应该更改Java端的格式,还是应该将Mat对象传递给jni那里的颜色空间并进行转换.

Dan*_*dro 3

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

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

// In Java
public static native boolean nativeCanny(long iAddr);
Run Code Online (Sandbox Code Playgroud)

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

// In Java
nativeCanny(myImage.getNativeObjAddr());
Run Code Online (Sandbox Code Playgroud)

此函数在 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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