Самый эффективный способ отправки изображения в YUV_420_888 с Android на JNI в OpenCV Mat - PullRequest
0 голосов
/ 04 июня 2018

У меня есть приложение для Android, в котором я хочу запустить OpenCV обработку изображений на живых изображениях из Android Camera2 API.В настоящее время, если я не выполняю никакой обработки, я могу получать изображения в функции OnImageAvailble со скоростью 30 кадров в секунду для обычного кадра 1280x720.

Теперь, как грязный взлом, я запрашиваю изображения у ImageReader в формате JPEG с последующей передачей растрового изображения в jni, что значительно снижает производительность.

Какой самый эффективный способ передачи кадра YUV в jni в cv Mat объекте.Также я хочу преобразовать этот кадр в RGB для дальнейшей обработки.Следует ли изменить формат на стороне Java или передать объект Mat в jni и преобразовать только цветовое пространство там.

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Может быть полезно для вас: так как мы много занимаемся обработкой изображений, мы написали библиотеку для этой цели в нашей компании.Он не написан на С, но довольно производительный.После преобразования вы можете просто передать указатель Mat на код C через JNI.

Он преобразует YUV (стандартный формат камеры Android YUV_420_888) в RGB Mats.Кроме того, он также позволяет эффективно обрезать YUV перед преобразованием (это важно для очень больших изображений, в противном случае вам потребуется преобразовать все изображение, а затем обрезать, что дорого).Использование очень просто:

Mat mat = Yuv.toMat(image)

https://github.com/quickbirdstudios/yuvToMat

0 голосов
/ 20 июня 2018

Все, что вы делаете в C ++, намного быстрее, чем эквивалент Java по очевидным причинам, включая преобразования YUV в RGB (даже если реализация Java опирается на скомпилированные библиотеки).

Вы можете напрямую передать указатель из вашегоСуществующий Mat в Java напрямую в C ++ через JNI.Предположим, я хочу сделать Canny () с использованием C ++ и JNI, и у меня есть функция JNI, определенная следующим образом:

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

Обратите внимание на параметр long iAddr , это прямой указатель на мойМат на Яве.Вы вызываете его так:

// 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, в конце концов, это указатель, поэтому мы никогда не делали копию.

Насколько я знаю, это так быстро, как только может.

...