2012-05-12 14 views
7

Estoy intentando comprimir sin pérdidas una imagen, y para aprovechar las regularidades, quiero convertir la imagen de RGB a Y'CbCr. (Los detalles exactos de lo que quiero decir con RGB e Y'CbCr no son importantes aquí; los datos RGB constan de tres bytes, y tengo tres bytes para almacenar el resultado).Transformación sin pérdida de RGB a Y'CbCr

El proceso de conversión en sí es bastante sencillo , pero hay un problema: aunque la transformación es matemáticamente invertible, en la práctica habrá errores de redondeo. Por supuesto, estos errores son pequeños y prácticamente imperceptibles, pero significa que el proceso ya no es sin pérdidas.

Mi pregunta es: ¿existe una transformación que convierta tres enteros de ocho bits (representando componentes rojos, verdes y azules) en otros tres enteros de ocho bits (representando un espacio de color similar a Y'CbCr, donde dos componentes cambiar solo ligeramente con respecto a la posición, o al menos menos que en un espacio de color RGB), y que se puede invertir sin pérdida de información?

Respuesta

14

YCoCg24

Aquí es una transformación de color que llamo "YCoCg24" que que convierte tres enteros de ocho bits (que representan los componentes rojo, verde y azul) en tres otros ocho bits (firmado) enteros (que representan un espacio de color similar a Y'CbCr), y es biyectiva (y por lo tanto se puede invertir sin pérdida de información):

G   R   B  Y   Cg   Co 
|   |   |  |   |   | 
|   |->-(-1)->(+) (+)<-(-/2)<-|   | 
|   |   |  |   |   | 
|   (+)<-(/2)-<-|  |->-(+1)->(+)   | 
|   |   |  |   |   | 
|->-(-1)->(+)   |  |   (+)<-(-/2)<-| 
|   |   |  |   |   | 
(+)<-(/2)-<-|   |  |   |->-(+1)->(+) 
|   |   |  |   |   | 
Y   Cg   Co G   R   B 

forward transformation  reverse transformation 

o en pseudocódigo:

function forward_lift(x, y): 
    signed int8 diff = (y - x) mod 0x100 
    average = (x + (diff >> 1)) mod 0x100 
    return (average, diff) 

function reverse_lift(average, signed int8 diff): 
    x = (average - (diff >> 1)) mod 0x100 
    y = (x + diff) mod 0x100 
    return (x, y) 

function RGB_to_YCoCg24(red, green, blue): 
    (temp, Co) = forward_lift(red, blue) 
    (Y, Cg) = forward_lift(green, temp) 
    return(Y, Cg, Co) 

function YCoCg24_to_RGB(Y, Cg, Co): 
    (green, temp) = reverse_lift(Y, Cg) 
    (red, blue) = reverse_lift(temp, Co) 
    return(red, green, blue) 

Algunos colores ejemplo:

color  R G B  Y CoCg24 
white  0xFFFFFF 0xFF0000 
light grey 0xEFEFEF 0xEF0000 
dark grey 0x111111 0x110000 
black  0x000000 0x000000 

red  0xFF0000 0xFF01FF 
lime  0x00FF00 0xFF0001 
blue  0x0000FF 0xFFFFFF 

G, R-G, B-G espacio de color

Otra transformación de color que convierte tres enteros de ocho bits en otros tres enteros de ocho bits.

function RGB_to_GCbCr(red, green, blue): 
    Cb = (blue - green) mod 0x100 
    Cr = (red - green) mod 0x100 
    return(green, Cb, Cr) 

function GCbCr_to_RGB(Y, Cg, Co): 
    blue = (Cb + green) mod 0x100 
    red = (Cr + green) mod 0x100 
    return(red, green, blue) 

Algunos colores ejemplo:

color  R G B  G CbCr 
white  0xFFFFFF 0xFF0000 
light grey 0xEFEFEF 0xEF0000 
dark grey 0x111111 0x110000 
black  0x000000 0x000000 

comentarios

Parece que hay un buen número lossless color space transforms. Se mencionan varias transformaciones de espacio de color sin pérdidas en Henrique S. Malvar, et al."Lifting-based reversible color transformations for image compression"; existe la transformación del espacio de color sin pérdida en JPEG XR; la transformada de color reversible original (ORCT) utilizada en varias propuestas "lossless JPEG"; G, R-G, B-G espacio de color; etc. Malvar et al parecen muy entusiasmados con la representación de 26 bits de YCoCg-R de un píxel RGB de 24 bits.

Sin embargo, casi todos requieren más de 24 bits para almacenar el color del píxel transformado.

La técnica "lifting" que uso en YCoCg24 es similar a la de Malvar et al y a la transformación de espacio de color sin pérdida en JPEG XR.

Debido adición es reversible (y adición módulo 0x100 es biyectiva), cualquier transformar de (a, b) a (x, y) que puede ser producido por el siguiente Feistel network es reversible y biyectiva:

a  b 
|  | 
|->-F->-(+) 
|  | 
(+)-<-G-<-| 
|  | 
x  y 

donde (+) indica la adición de 8 bits (módulo 0x100), abxy son todos valores de 8 bits, y F y G indican cualquier función arbitraria.

detalles

¿Por qué sólo tiene 3 bytes para almacenar el resultado en? Eso suena como un contraproducente premature optimization. Si su objetivo es comprimir sin pérdidas una imagen en un archivo comprimido lo más pequeño posible en un período de tiempo razonable, entonces el tamaño de las etapas intermedias es irrelevante. Incluso puede ser contraproducente: una representación intermedia "más grande" (como Transformación de color reversible o YCoCg-R de 26 bits) puede dar como resultado un tamaño de archivo comprimido final más pequeño que una representación intermedia "más pequeña" (como RGB o YCoCg24).

EDITAR: Oopsies. Cualquiera de "(x) mod 0x100" o "(x) & 0xff" da exactamente los mismos resultados - los resultados que quería. Pero de alguna manera los mezclé para producir algo que no funcionaría.

+0

Gracias por esta respuesta elaborada. La razón del requisito de 24 bits es práctica. Entiendo que trabajar con una etapa intermedia de 26 bits puede mejorar la relación de compresión (de hecho, hubo múltiples etapas intermedias que aumentaron el tamaño de la transmisión). Sin embargo, el algoritmo que estaba usando opera en bytes individuales, no en bits. Al tratar el flujo de bits como un flujo de bytes, perdería las bonitas propiedades que presenta la transformación del espacio de color. – Ruud

+0

Sí, cada vez que cambio un sistema de una secuencia de bytes a una secuencia de bits, el sistema suele tardar unas 8 veces más en ejecutarse y es mucho más difícil de depurar. Entonces simpatizo con tu deseo de seguir con los flujos de bytes si es posible. –

+0

David, esta es una transformación muy buena. Muchas gracias por brindarlo. Una cosa a tener en cuenta, su reverse_lift debería devolver x e y, no promedio y diff. – MoDJ

2

Encontré una de esas soluciones, utilizada por JPEG 2000. Se llama Transformada de Color Reversible (RCT), y se describe en Wikipedia, así como en JPEG site (aunque los métodos de redondeo no son consistentes). Sin embargo, los resultados no son tan buenos como con la transformación de color irreversible.

También encontré un método mejor descrito en el documento Transformaciones de color enteros a enteros reversibles mejorados por Soo-Chang Pei y Jian-Jiun Ding. Sin embargo, los métodos descritos en ese documento, y el método utilizado por JPEG 2000, requieren bits adicionales para almacenar el resultado. Esto significa que los valores transformados ya no caben en 24 bits.