2011-08-12 20 views
11

El algoritmo utilizado por PIL v1.1.7 ofrece resultados de búsqueda "lavados". Al convertir los mismos datos de origen usando ffmpeg parece correcto. El uso de mplayer da resultados idénticos a ffmpeg (quizás utilicen la misma biblioteca debajo). Esto me lleva a creer que PIL puede estar saturando las conversiones de espacio de color. La conversión parece tener origen en libImaging/ConvertYCbCr.c:Conversión de espacio de color de PIL YCbCr -> RGB

/* JPEG/JFIF YCbCr conversions 

    Y = R * 0.29900 + G * 0.58700 + B * 0.11400 
    Cb = R * -0.16874 + G * -0.33126 + B * 0.50000 + 128 
    Cr = R * 0.50000 + G * -0.41869 + B * -0.08131 + 128 

    R = Y +      + (Cr - 128) * 1.40200 
    G = Y + (Cb - 128) * -0.34414 + (Cr - 128) * -0.71414 
    B = Y + (Cb - 128) * 1.77200 

*/ 

esto es sólo un comentario en la fuente, por supuesto que es de código C y la función real se implementa con tablas de búsqueda no multiplicación de matrices (la static INT16 R_Cr etc. cortó por razones de brevedad):

void 
ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels) 
{ 
    int x; 
    UINT8 a; 
    int r, g, b; 
    int y, cr, cb; 

    for (x = 0; x < pixels; x++, in += 4, out += 4) { 

     y = in[0]; 
     cb = in[1]; 
     cr = in[2]; 
     a = in[3]; 

     r = y + ((   R_Cr[cr]) >> SCALE); 
     g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE); 
     b = y + ((B_Cb[cb]   ) >> SCALE); 

     out[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r; 
     out[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g; 
     out[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b; 
     out[3] = a; 
    } 
} 

he buscado en Google, pero parece que hay una gran confusión acerca de la manera 'correcta' de hacer esta conversión de espacio de color. Entonces mi pregunta es: ¿es correcto lo anterior? Y si no, ¿cuál es la mejor manera?


edición: Después de leer los enlaces proporcionados por Mark Ransom, he descubierto que existen conflictos con las definiciones en función de si se utiliza toda la gama de YCbCr o la abrazadera a la gama válida. Ver enlaces de abajo para más información:

Parece la versión PIL está utilizando el algoritmo incorrecto, por lo que he rodado mi propia función para la conversión que da la correcta buscando resultados (versión "SDTV"). Código que se incluye a continuación, para los futuros lectores a utilizar:

from numpy import dot, ndarray, array 

def yuv2rgb(im, version='SDTV'): 
    """ 
    Convert array-like YUV image to RGB colourspace 

    version: 
     - 'SDTV': ITU-R BT.601 version (default) 
     - 'HDTV': ITU-R BT.709 version 
    """ 
    if not im.dtype == 'uint8': 
     raise TypeError('yuv2rgb only implemented for uint8 arrays') 

    # clip input to the valid range 
    yuv = ndarray(im.shape) # float64 
    yuv[:,:, 0] = im[:,:, 0].clip(16, 235).astype(yuv.dtype) - 16 
    yuv[:,:,1:] = im[:,:,1:].clip(16, 240).astype(yuv.dtype) - 128 

    if version.upper() == 'SDTV': 
     A = array([[1.,     0., 0.701   ], 
        [1., -0.886*0.114/0.587, -0.701*0.299/0.587], 
        [1., 0.886,        0.]]) 
     A[:,0] *= 255./219. 
     A[:,1:] *= 255./112. 
    elif version.upper() == 'HDTV': 
     A = array([[1.164,  0., 1.793], 
        [1.164, -0.213, -0.533], 
        [1.164, 2.112,  0.]]) 
    else: 
     raise Exception("Unrecognised version (choose 'SDTV' or 'HDTV')") 

    rgb = dot(yuv, A.T) 
    result = rgb.clip(0, 255).astype('uint8') 

    return result 
+1

¿Coincide con uno de los mecanismos en http://en.wikipedia.org/wiki/YCbCr? –

Respuesta

7

Si nos fijamos en las definiciones de Wikipedia, se puede ver que hay dos definiciones contradictorias para YCbCr. La definición ITU-R BT.601 comprime los valores en el rango 16-235 para proporcionar espacio para pies y espacio libre, mientras que la versión JPEG usa el rango completo 0-255. Si tuviera que decodificar valores en el espacio BT.601 utilizando la fórmula para JPEG, el resultado definitivamente se vería borroso.

+1

gracias, esto me puso en el camino correcto, y encontré una explicación clara de los diversos estándares (¿oxímoron?) Aquí -> http://www.equasys.de/colorconversion.html – wim

Cuestiones relacionadas