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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在YUV_420_888中将图像从Android发送到OpenCV Mat中的JNI的最有效方式相关的知识,希望对你有一定的参考价值。

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

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

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

答案

由于显而易见的原因,你在C ++中所做的任何事情都比Java等同得多,包括YUV到RGB的转换(即使Java实现依赖于编译库)。

您可以直接将指针从Java中现有的Mat直接传递给C ++到JNI。假设我想使用C ++和JNI做Canny(),我有一个像这样定义的JNI函数:

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

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

据我所知,这是最快的。

另一答案

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

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

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat

以上是关于在YUV_420_888中将图像从Android发送到OpenCV Mat中的JNI的最有效方式的主要内容,如果未能解决你的问题,请参考以下文章

使用新的 Android camera2 api 从 YUV_420_888 进行 JPEG 编码时的绿色图像

在Android camera2下将YUV_420_888转换为位图的图像不正确

Android Camera App 使用 CameraX 将图像保存为 YUV_420_888 格式

如何保存 YUV_420_888 图像?

将android.media.Image(YUV_420_888)转换为Bitmap

camera2 如何从图像读取器侦听器中的 YUV_420_888 图像中获取 Exif 数据