Convirtiendo YUV en BGR o RGB en OpenCV

Tengo una tarjeta de captura de TV que tiene un feed en formato YUV. He visto otras publicaciones similares a esta pregunta e intenté probar todos los métodos posibles indicados, pero ninguno de ellos proporcionó una imagen clara. Por el momento, los mejores resultados se obtuvieron con la cvCvtColor(scr, dst, CV_YUV2BGR) a la función OpenCV cvCvtColor(scr, dst, CV_YUV2BGR) .

Actualmente no estoy al tanto del formato YUV y para ser honesto me confunde un poco, ya que parece que almacena 4 canales, pero solo tiene 3? He incluido una imagen de la tarjeta de captura para esperar que alguien pueda entender qué es lo que está sucediendo y que podría usar para completar los espacios en blanco.

Imagen convertida de YUV a BGR

La alimentación entra a través de una tarjeta DeckLink Intensity Pro y se accede a ella en una aplicación C ++ utilizando OpenCV en un entorno Windows 7.

Actualizar

Miré un artículo de Wikipedia sobre esta información e intenté usar la fórmula en mi aplicación. A continuación se muestra el bloque de código con la salida recibida de él. Cualquier consejo es muy apreciado.

 BYTE* pData; videoFrame->GetBytes((void**)&pData); m_nFrames++; printf("Num Frames executed: %d\n", m_nFrames); for(int i = 0; i imageData[i] = pData[i] + pData[i+2]*((1 - 0.299)/0.615); m_RGB->imageData[i+1] = pData[i] - pData[i+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[i+2]*((0.299*(1 - 0.299))/(0.615*0.587)); m_RGB->imageData[i+2] = pData[i] + pData[i+1]*((1 - 0.114)/0.436); } 

Intento de conversión RGB

Me parece que estás decodificando una transmisión YUV422 como YUV444. Pruebe esta modificación al código que proporcionó:

 for(int i = 0, j=0; i < 1280 * 720 * 3; i+=6, j+=4) { m_RGB->imageData[i] = pData[j] + pData[j+3]*((1 - 0.299)/0.615); m_RGB->imageData[i+1] = pData[j] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587)); m_RGB->imageData[i+2] = pData[j] + pData[j+1]*((1 - 0.114)/0.436); m_RGB->imageData[i+3] = pData[j+2] + pData[j+3]*((1 - 0.299)/0.615); m_RGB->imageData[i+4] = pData[j+2] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587)); m_RGB->imageData[i+5] = pData[j+2] + pData[j+1]*((1 - 0.114)/0.436); } 

No estoy seguro de que tenga sus constantes correctas, pero en el peor de los casos sus colores estarán apagados, la imagen debería ser reconocible.

En la versión más nueva de OPENCV hay una función incorporada que se puede usar para hacer la conversión de YUV a RGB

cvtColor(src,dst,CV_YUV2BGR_YUY2);

especifique el formato YUV después del guión bajo, como este CV_YUYV2BGR_xxxx

El software BlackMagic Intensity devuelve el formato YUVY ‘en bmdFormat8BitYUV, por lo que 2 fonts de píxeles se comprimen en 4 bytes; no creo que cvtColor de openCV pueda manejar esto.

Puede hacerlo usted mismo, o simplemente llamar a la función ConvertFrame () del software Intensity.

editar: YUV normalmente se almacena como
enter image description here

Hay un Y (brillo) para cada píxel, pero solo un U y un V (color) para cada píxel alterno en la fila.

Entonces, si los datos son un carácter sin signo que apunta al inicio de la memoria como se muestra arriba.

píxel 1, Y = datos [0] U = datos [+1] V = datos [+3]
píxel 2, Y = datos [+2] U = datos [+1] V = datos [+3]

Luego usa los coeficientes YUV-> RGB que usaste en tu código de muestra.

Puede ser el camino equivocado, pero muchas personas (es decir, ingenieros) mezclan YUV con YCbCr.

Intentar

 cvCvtColor(src, dsc, CV_YCbCr2RGB) 

o CV_YCrCb2RGB o tal vez un tipo más exótico.

Tal vez alguien está confundido por los modelos de color YCbCr y YUV. Opencv no maneja YCbCr . En cambio, tiene YCrCb , y se implementó de la misma manera que YUV en opencv.

De las fonts de opencv https://github.com/Itseez/opencv/blob/2.4/modules/imgproc/src/color.cpp#L3830 :

 case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: // ... // 1 if it is BGR, 0 if it is RGB bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2; //... converting to YUV with the only difference that brings // order of Blue and Red channels (variable bidx) 

Pero hay una cosa más que decir.
Actualmente hay un error en la conversión CV_BGR2YUV y CV_RGB2YUV en OpenCV twig 2.4. *.

En la actualidad, esta fórmula se utiliza en la implementación:

 Y = 0.299B + 0.587G + 0.114R U = 0.492(RY) V = 0.877(BY) 

Lo que debería ser (según wikipedia ):

 Y = 0.299R + 0.587G + 0.114B U = 0.492(BY) V = 0.877(RY) 

Los canales Rojo y Azul están fuera de lugar en la fórmula implementada.

Posible solución para convertir BGR-> YUV mientras el error no está solucionado:

  cv::Mat source = cv::imread(filename, CV_LOAD_IMAGE_COLOR); cv::Mat yuvSource; cvtColor(source, yuvSource, cv::COLOR_BGR2RGB); // rearranges B and R in the appropriate order cvtColor(yuvSource, yuvSource, cv::COLOR_BGR2YUV); // yuvSource will contain here correct image in YUV color space