Saturday, May 24, 2008

Óleo digital ¡a color!

Hace un par de mensajes (vea aquí), hablé de mi programa para convertir fotografías en similares pero semejantes a pinturas al óleo. La primera versión trabajaba con tonos de gris. La virtud de esto es que es mucho más fácil de programar, pues sólo se tienen 256 posibles tonos de gris. En este caso, el procedimiento del óleo digital implica tomar una vecindad de 7x7 pixeles, sacar la frecuencia de los mismos y pintar, en el pixel de interés, el color que más frecuencia haya tenido en la malla de 7x7 pixeles. Hacer el histograma para tonos de gris es fácil, pues simplemente creamos un arreglo de 256 valores de frecuencia (de 0 a 255) y cuando hallamos un tono de gris, tomamos éste como el índice e incrementamos la frecuencia de ese valor específicamente. Al terminar esto, simplemente sacamos el máximo de las frecuencias y el índice nos dice qué tono de gris tenemos que poner.

Sin embargo, al querer pasar a color, tenemos que las imágenes pueden contener poco más de 16 millones de colores. Esto, obviamente hace el problema un poco más difícil, pues no podemos generar un arreglo de 16 millones de colores (para seguir con la técnica usada en la parte en tonos de gris), pues es totalmente ineficiente y absurdo. Así, aquí hay que contar y crear el histograma de frecuencias de manera más sencilla. Después de dos semanas de darle la vuelta al problema, finalmente hallé una solución simple. La implementé y de pronto ya tenía mi programa que generaba el óleo digital en color.

Encontré sin embargo un par de problemas. Uno fue el hecho de que en color, el filtro a veces mete ruido cuando hay puntos blancos. Así, decidí que necesitaba usar el filtro "blur" para quitarle ese ruido. El resultado final es ahora mucho más aceptable.

Quien quiera probar mi software, mándeme un correo a morsa@la-morsa.com y a vuelta del mismo lo tendrá de forma gratuita en su buzón electrónico.

4 comments:

Yixus said...

¿No bastaba con hacer tres arreglos de 0 a 255 para R, G y B respectivamente? ¿Cómo le hiciste al final?

Morsa said...

No, no s epodía hacer eso que dices. El algoritmo indica que de los 49 pixeles, debes sacar la frecuencia de cada color y poner, en el punto de interés, el color que tenga mayor frecuencia. Si haces tres arreglos y separas los RGBs, ¿cómo sabes entonces las frecuencias de cada color?

Lo que hice fue una rutina que lo que hace es, precisamente, hacer un arreglo de frecuencias de los 49 puntos. El código es éste:

//ahora sacamos el perfil de frecuencias...
ColValor[1] := Colores[1];
FrecValor := 1;
Frec[FrecValor] := 1;

for x := 2 to LimSup do
begin
if Colores[x-1] = Colores[x] then
begin //si son iguales
Frec[FrecValor] := Frec[FrecValor] + 1;
end
else
begin //si son diferentes
inc(FrecValor);
ColValor[FrecValor] := Colores[x];
Frec[FrecValor] := 1;
end;
end;

Evidentemente las variables x, i, frecvalor, etc, están definidas...

saludos
Manuel

Yixus said...

¿Qué pasa si todos los pixeles de la malla tienen diferentes colores? Aunque supongo que es muy improbable (es decir, sé que "no pasa nada", eliges uno y ya, pero ¿tu algoritmo cuál toma?)

Morsa said...

Elige el primero. Si todos son pixeles diferentes, da lo mismo elegir uno u otro.

Saludos