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

时间:2018-06-04 09:11:13

标签: java android opencv java-native-interface opencv4android

我有一个Android应用程序,我想在android OpenCV API的实时图像上运行一些Camera2图像处理。目前,如果我不进行任何处理,我可以使用OnImageAvailble功能以30 fps的速度接收常规1280x720帧的图片。

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

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

2 个答案:

答案 0 :(得分:2)

由于明显的原因,包括YUV到RGB的转换(即使Java实现依赖于编译的库),使用C ++所做的任何事情都比Java更快。

您可以通过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 ++中此函数的实现将以与此类似的方式接收此指针(如果不起作用,请用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中,毕竟它是一个指针,所以我们从不复制。

据我所知,这就是最快的速度。

答案 1 :(得分:2)

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

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

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat