将 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)
我有一个 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)