Repito lo mismo que Joseba Muchísimas gracias, Metí este tema la semana pasada, no he podido continuarlo y sin embargo he visto con mucho agrado que entre todos se le van encontrando soluciones.
Sigo con el curro malo (Las entregas de trabajo!!!) que no he tenido tiempo para utilizar todos los recursos que habeís compartido. Hoy probaré todo esto que tiene muy buena pinta. Richard Joseba Alonso <[EMAIL PROTECTED]> escribió: ¡Cojonudo! Gracias por compartir esto :) P.D: Es probable que el email no llegase al responder por superar los 100Kb, tamaño maximo de mensaje permitido en la lista. Lo he subido a 300... Un saludo, Joseba > -----Mensaje original----- > De: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] En nombre de Miguel Angel Sánchez > Enviado el: miércoles, 05 de julio de 2006 14:31 > Para: Lista dedicada a Actionscript > Asunto: [ASNativos] Detectar imágenes con colores similares > > Finalmente pude sacar algo de tiempo libre para hacer la > clase que obtiene el color promedio de una imagen a través de > su histograma de color. > > Os explico como va el tema: > - Es un sistema de votación, tenemos una matriz > tridimensional histograma[r][g][b] inicializada a ceros. > - Recorremos cada pixel de la imagen y obtenemos su > componente r, g y b. > - Con esas 3 componentes incrementaremos el valor de la casilla > correspondiente: histograma[r][g][b]++ > - Finalmente, la casilla que mayor valor tenga será la del > color dominante > > Puntualizaciones: > - Para sacar el color con error cero, habría que crear una > matriz histograma[256][256][256], que consumiría demasiada > memoria y tiempo para rellenarla. > - Lo que se hace para reducir tiempo y memoria es discretizar > el histograma a, por ejemplo, [64][64][64], de forma que el > pixel con valores de rgb 32,64,128 en lugar de votar por la > casilla [32][64][128], votaría por la casilla [8][16][32], ya > que hemos dividido el espacio de colores entre 4. Esto > significa que el color 33,65,129 votaría por la misma casilla > que el color anterior, pero este error es admisible ya que a > simple vista no podremos diferenciar un color de otro. > - Varios ejemplos de color promedio dependiendo del número de > niveles en el que hayamos dividido el histograma: > - [20][20][20] -> rgb = 26 64 13 > - [40][40][40] -> rgb = 45 51 32 > - [50][50][50] -> rgb = 46 51 36 > - [80][80][80] -> rgb = 48 51 35 > - [150][150][150] -> rgb = 49 53 38 > - [180][180][180] -> rgb = 50 53 38 > - Como se puede observar, a mayor número de niveles más > preciso es el algoritmo, pero mucho más tiempo y memoria > consume. Con 50 niveles ya obtenemos un color aceptable que > no dista mucho del promedio real, y a simple vista es inapreciable. > > A continuación os pongo la clase sin optimizaciones para que sea más > legible: > > public static function getColorPromedioSinOptimizar(bitmap:BitmapData, > niveles:Number):Number { > var histograma:Array = []; > for (var i:Number=0; i > histograma[i] = []; > for (var j:Number=0; j > histograma[i][j] = []; > for (var k:Number=0; k > histograma[i][j][k] = 0; > } > } > } > > var rango:Number = 256 / niveles; > var colorPromedio:Number = 0; > var mayor:Number = 0; > > var w:Number = bitmap.width; > var h:Number = bitmap.height; > var totalPixeles:Number = w*h; > var valorVotacion:Number = 1 / totalPixeles; > for (var i:Number=0; i > for (var j:Number=0; j > var color:Number = bitmap.getPixel(i, j); > var r:Number = (color >> 16) & 0xFF; > var g:Number = (color >> 8) & 0xFF; > var b:Number = color & 0xFF; > r = Math.floor(r / rango); > g = Math.floor(g / rango); > b = Math.floor(b / rango); > histograma[r][g][b] += valorVotacion; > if (histograma[r][g][b] > mayor) { > mayor = histograma[r][g][b]; > colorPromedio = color; > } > } > } > return colorPromedio; > } > > > Y a continuación la clase optimizada, que es menos legible > pero funciona casi el doble de rápido: > > public static function getColorPromedio(bitmap:BitmapData, > niveles:Number):Number { > var histo:Array = []; > for (var i:Number=niveles-1; i>=0; i--) { > histo[i] = []; > var histo1:Array = histo[i]; > for (var j:Number=niveles-1; j>=0; j--) { > histo1[j] = []; > var histo2:Array = histo1[j]; > for (var k:Number=niveles-1; k>=0; k--) { > histo2[k] = 0; > } > } > } > > var rango:Number = 256 / niveles; > var rangos:Array = []; > var f:Function = Math.floor; > for (var i:Number=0; i<256; i++) { > rangos[i] = f(i / rango); > } > > var w:Number = bitmap.width; > var h:Number = bitmap.height; > var valorVotacion:Number = 1 / (w*h); > > var colorPromedio:Number = 0; > var mayor:Number = 0; > > for (var i:Number=0; i > for (var j:Number=0; j > var color:Number = bitmap.getPixel(i, j); > var r:Number = rangos[(color >> 16) & 0xFF]; > var g:Number = rangos[(color >> 8) & 0xFF]; > var b:Number = rangos[(color & 0xFF)]; > histo[r][g][b] += valorVotacion; > if (histo[r][g][b] > mayor) { > mayor = histo[r][g][b]; > colorPromedio = color; > } > } > } > return colorPromedio; > } > > > Es un método estático que podéis incluir en vuestras clases > ColorUtils o similares. El primer parámetro es un objeto > BitmapData con la imagen y el segundo es el número de niveles > en el que vamos a dividir el histograma. > > Un ejemplo de uso podría ser este: > > //imagen es un MovieClip con una imagen dentro en su > coordenada (0,0) var bmp:BitmapData = new > BitmapData(imagen._width, imagen._height); bmp.draw(imagen); > > var colorPromedio:Number = ColorUtil.getColorPromedio(bmp, 50); > > //resultado es un MovieClip con un cuadrado negro //lo > coloreo para ver el color promedio de la imagen var c:Color = > new Color(timeline.resultado); c.setRGB(colorPromedio); > > Y para terminar este pedazo de tocho, un poco de benchmarks en un AMD > 2500XP: > - Imagen 330x374 con 80 niveles (versión sin optimizar): 5.5 > - 5.7 segundos > - Imagen 330x374 con 80 niveles (versión optimizada): 3.2 - > 3.4 segundos > > Para imágenes más pequeñas o menos niveles, evidentemente > menos tiempo. > > Saludos > > [Perdonad que no siga el hilo anterior pero le doy a > responder y no aparecen los mensajes en la lista :-/ ] > > ----------------------------------------------------- > ASNativos > www.5dms.com > subscripciones/desubscripciones > http://asnativos.5dms.com > ----------------------------------------------------- > > ----------------------------------------------------- ASNativos www.5dms.com subscripciones/desubscripciones http://asnativos.5dms.com ----------------------------------------------------- --------------------------------- LLama Gratis a cualquier PC del Mundo. Llamadas a fijos y móviles desde 1 céntimo por minuto. http://es.voice.yahoo.com ----------------------------------------------------- ASNativos www.5dms.com subscripciones/desubscripciones http://asnativos.5dms.com -----------------------------------------------------

