Zajmuję się tworzeniem aplikacji kamery opartej na Camera API 2
i znalazłem kilka problemów przy użyciu libyuv. Chcę konwertować obrazy YUV_420_888
pobrane z ImageReadera, ale mam pewne problemy ze skalowaniem na powierzchni podlegającej powtórnemu przetworzeniu.Problemy podczas skalowania obrazu YUV przy użyciu biblioteki libyuv
W skrócie: obrazy wychodzą z tonami zielonymi zamiast odpowiadających im dźwięków (eksportuję pliki .yuv i sprawdzam je za pomocą http://rawpixels.net/).
można zobaczyć przykład wejściowego tutaj:
i co ja dostać po tym, jak wykonać skalowanie:
Chyba robię coś złego z krokami, lub dostarczanie nieprawidłowy format YUV (może ja trzeba przekształcić obraz na inny format?). Nie mogę jednak ustalić, gdzie jest błąd, ponieważ nie wiem, jak skorelować zielony kolor z algorytmem skalowania.
To jest kod konwersji, którego używam, możesz zignorować zwrot NULL, ponieważ jest dalsze przetwarzanie, które nie jest związane z problemem.
#include <jni.h>
#include <stdint.h>
#include <android/log.h>
#include <inc/libyuv/scale.h>
#include <inc/libyuv.h>
#include <stdio.h>
#define LOG_TAG "libyuv-jni"
#define unused(x) UNUSED_ ## x __attribute__((__unused__))
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS_)
struct YuvFrame {
int width;
int height;
uint8_t *data;
uint8_t *y;
uint8_t *u;
uint8_t *v;
};
static struct YuvFrame i420_input_frame;
static struct YuvFrame i420_output_frame;
extern "C" {
JNIEXPORT jbyteArray JNICALL
Java_com_android_camera3_camera_hardware_session_output_photo_yuv_YuvJniInterface_scale420YuvByteArray(
JNIEnv *env, jclass /*clazz*/, jbyteArray yuvByteArray_, jint src_width, jint src_height,
jint out_width, jint out_height) {
jbyte *yuvByteArray = env->GetByteArrayElements(yuvByteArray_, NULL);
//Get input and output length
int input_size = env->GetArrayLength(yuvByteArray_);
int out_size = out_height * out_width;
//Generate input frame
i420_input_frame.width = src_width;
i420_input_frame.height = src_height;
i420_input_frame.data = (uint8_t *) yuvByteArray;
i420_input_frame.y = i420_input_frame.data;
i420_input_frame.u = i420_input_frame.y + input_size;
i420_input_frame.v = i420_input_frame.u + input_size/4;
//Generate output frame
free(i420_output_frame.data);
i420_output_frame.width = out_width;
i420_output_frame.height = out_height;
i420_output_frame.data = new unsigned char[out_size * 3/2];
i420_output_frame.y = i420_output_frame.data;
i420_output_frame.u = i420_output_frame.y + out_size;
i420_output_frame.v = i420_output_frame.u + out_size/4;
libyuv::FilterMode mode = libyuv::FilterModeEnum::kFilterBilinear;
int result = I420Scale(i420_input_frame.y, i420_input_frame.width,
i420_input_frame.u, i420_input_frame.width/2,
i420_input_frame.v, i420_input_frame.width/2,
i420_input_frame.width, i420_input_frame.height,
i420_output_frame.y, i420_output_frame.width,
i420_output_frame.u, i420_output_frame.width/2,
i420_output_frame.v, i420_output_frame.width/2,
i420_output_frame.width, i420_output_frame.height,
mode);
LOGD("Image result %d", result);
env->ReleaseByteArrayElements(yuvByteArray_, yuvByteArray, 0);
return NULL;
}
Dla tego, co jest warte, pełny zielony obraz YUV prawdopodobnie oznacza, że twoje "byteArray" jest pełne 0. –
to nie jest, dane z 3 wejściowych i wyjściowych tetrad mają info: –
@FranciscoDurdinGarcia czy próbowałeś mojej odpowiedzi? – gmetax