Showing posts with label difusión del error. Show all posts
Showing posts with label difusión del error. Show all posts
Saturday, November 17, 2018
Dithering: su fundamento
Hoy en día contamos con tarjetas gráficas que pueden mostrar luminosos colores en la pantalla de la computadora. Vamos, hasta los teléfonos ya tienen resoluciones de alta definición en muchos casos y pueden desplegar millones de diferentes colores. Considerando esto, resulta quizás para algún lector un poco absurdo que alguien quiera pasar una imagen en tonos de grises a blanco y negro, pero esto es un proceso que se hace continuamente cuando, por ejemplo, queremos imprimir una fotografía (en color o tonos de grises), teniendo solamente un dispositivo que imprime con tinta negra.
Es decir, tenemos dos posibles colores: puntos negros (tinta) y puntos blancos (sin tinta). Con ello debemos poder representar la imagen de la mejor manera, intentando no perder información o al menos, perder lo menos posible. Ya aquí hemos hablado de algunos procesos interesantes para hacer esto. Uno de ellos es el “dithering al azar” (o random), o bien, el usar la técnica de los semitonos. Los resultados con ambos procedimientos pueden ser mejores o peores, de acuerdo muchas veces a la imagen a procesar.
Sin embargo, el tema no se ha agotado. El dithering finalmente se basa en algo fundamental, que es la difusión del error de un punto al siguiente. Por ejemplo, consideremos que en una imagen en tonos de gris (donde cada punto tiene el mismo valor en rojo, verde y azul), en RGB, y veamos una de las coordenadas, por ejemplo el ROJO. Supongamos que en una línea de pixeles tenemos los valores 0, 96, 96, …, etcétera. Veamos cómo podemos hacer dithering usando esta difusión de error de punto a punto.
Si vemos el primer pixel, hallaremos que el primer valor es cero, que es negro, por lo que mandaremos a la impresora para que pinte en el papel un punto negro. Pasamos al siguiente y vemos que es un 96. ¿Este valor está más cerca o más lejos del negro? La respuesta es simple: si tenemos valores del 0 (negro) al 255 (blanco), entonces el 96 está más cerca del negro que del blanco. ¿Cuál es el error en este caso? 96 pasos, es decir, el tono de gris 96 está precisamente a 96 pasos del cero y esto es el error. Ahora tomemos el valor del siguiente ROJO. Hallamos que de nuevo es un tono de gris 96. Entonces vamos a hacer la difusión de error que acarreamos (96) al nuevo valor, que es 96. la suma de ambos da 192. Ahora nos preguntamos: ¿Este valor está más cerca o menos cerca del blanco? 192 está a 63 pasos del blanco. este es el error. Como es hacia el blanco, vamos a decir que está a -63 pasos. Pintaremos un punto blanco y el error se sumará al siguiente pixel.
Este elemental algoritmo, escrito en Delphi, se ve así:
Vayamos a las pruebas. Tomemos la foto de Ilse y pasémosla a tonos de gris:
Y procesémosla con este algoritmo. El resultado es éste:
Puede verse que el resultado no queda mal pero se ven algunos “artefactos”, es decir, ruido en la imagen o puntos indeseables. Tomemos ahora la imagen de Abraham Lincoln y observemos los resultados:
y el resultado:
Aquí las cosas mejoraron. La razón es que este método de difusión simple tiene dificultades cuando tiene que ir de blanco a negro y viceversa. Sin embargo, el asunto es que al hacer esta difusión del error, estamos aplicando le principio básico de todos estos mecanismos para hacer dithering.
En próximos artículo hablaremos de dithering más sofisticado, como el creado por Floyd-Steinberg.
Monday, April 24, 2017
Usando "Dithering"... O cuando la impresora es blanco y negro
Estamos acostumbrados a procesar imágenes con muchos colores. Las tarjetas gráficas actuales pueden desplegar 16 millones de colores y de hecho, ya el ojo no llega a distinguir diferencias entre algunos tonos. Esa parece ser la razón por la cual los fabricantes de hardware ya no buscan más colores o más resolución, pues estamos llegando a los límites que nuestro ojo puede percibir.
Pero curiosamente, a pesar de la gran tecnología que ahora tenemos ya incluso en nuestras casas, hay procedimientos que se necesitan seguir haciendo como hace ya muchos años. Por ejemplo, consideremos que tenemos una impresora que solamente usa tinta negra. En ese caso solamente tendremos dos posibles "colores" para imprimir: blanco (sin imprimir) y negro (impresión con tinta). Esto significa un problema, porque si tenemos una imagen en tonos de grises, es decir, con 256 posibles tonos de gris, entonces no podríamos imprimirla para que se viesen esos tonos.
El problema se puede solucionar si observamos cómo vemos e interpretamos. Por ejemplo, si hacemos una especie de tablero de ajedrez con dos colores, digamos rojo y azul, pues veremos una malla con colores alternativos. Pero hagamos las casillas más chicas. En la medida que las reducimos, podemos ver de pronto que el rojo y el azul se transforman en un violetas. Si usamos una lupa podremos ver que ese violeta no existe, lo que ocurre es que nuestro cerebro se encarga de interpretar así lo que vemos. Pues bien, esto es lo que se llama dithering y es el proceso que de alguna u otra manera usan las impresoras actuales cuando tienen que imprimir imágenes de las cuales no tienen todos los colores.
El "dithering" o tramado, tiene que ver con un concepto fundamental: "la difusión del error". Por ejemplo, supongamos que queremos imprimir la imagen en tonos de gris pero en una impresora que sólo tiene dos posibles colores, como mencionamos negro (tinta) y blanco (no tinta). Podemos entonces ejecutar el siguiente procedimiento: Consideremos que el primer pixel tiene un valor de 96 (considerando que es una imagen en tonos de gris en donde el Rojo, Verde y Azul de cada punto gráfico tiene el mismo valor). Podemos preguntarnos entonces ¿qué tan lejos está el valor 96 del 255 o del 0. ¿De cuál está más cerca? Hallaremos que el 96 está más cerca del 0 y entonces diremos que el error en la impresión es de 96 tonos. Es decir, como el 0 es el negro, el 96 está a esa cantidad de tonos del negro.
Consideremos ahora que el siguiente valor en nuestra imagen es también 96. Aquí es donde el dithering se usa. Tomamos el error y lo sumamos al pixel que estamos procesando. esto nos dará 192 y este valor está más cerca del blanco que del negro, por lo que pintamos un punto en blanco (es decir, no imprimimos nada en ese punto en la hoja) y vemos qué tan lejos está el 192 del 255. Veremos que está a -63 puntos de ese valor. Es decir, cuando me acerco al 255 el error es negativo. Cuando estoy más cerca del negro, el valor es positivo.
En la medida que seguimos con este algoritmo, veremos que estamos "difundiendo el error" de forma tal que el pixel anterior (y su error), inciden en el siguiente pixel y así sucesivamente. Cuando termino con una línea de pixeles, redefino la difusión del error en cero y vuelvo a empezar a procesar la siguiente línea.
Cabe señalar que hay que tener cuidado por si ocurre que un valor se sale de rango hacia arriba (mayor de 255) o hacia abajo (menor que cero). En este caso, la difusión del error es igual a cero.
El algoritmo básico (en Delphi) es éste:
begin
for i := 1 to Image1.Picture.Height do
begin
Application.ProcessMessages;
Error_Dif := 0;
k := 1;
for j := 1 to Image1.Picture.Width do
begin
R := (Image1.Canvas.Pixels[j,i] shr 16) and $FF;
NewByte := Error_Dif + R;
if NewByte >= 255 then
begin
NewByte := 255;
Image2.Canvas.Pixels[j,i] := RGB(255,255,255);
Error_Dif := 0;
end
else
if NewByte <= 0 then
begin
NewByte := 0;
Image2.Canvas.Pixels[j,i] := RGB(0,0,0);
Error_Dif := 0;
end
else
if 255 - NewByte > 127 then
begin
//pixel en negro
Image2.Canvas.Pixels[j,i] := RGB(0,0,0);
k := 1;
Error_Dif := NewByte * k;
end
else
begin
//pixel en blanco
Image2.Canvas.Pixels[j,i] := RGB(255,255,255);
k := -1;
Error_Dif := 255 - (NewByte);
Error_Dif := Error_Dif * k;
end;
end;
end;
Tomé una imagen ejemplo que usan en el artículo que leí (ver referencias), y hallé que mi resultado es el esperado.
En los próximos artículos seguiremos hablando de otras interesantes técnicas para hacer "dithering", algo que hacen las impresoras hoy en día y que muchos no estaban siquiera enterados de este proceso.
Referencias:
TannerHelland (blog)
Subscribe to:
Posts (Atom)








