¡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: > <code> > public static function getColorPromedioSinOptimizar(bitmap:BitmapData, > niveles:Number):Number { > var histograma:Array = []; > for (var i:Number=0; i<niveles; i++) { > histograma[i] = []; > for (var j:Number=0; j<niveles; j++) { > histograma[i][j] = []; > for (var k:Number=0; k<niveles; 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<w; i++) { > for (var j:Number=0; j<h; 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; > } > </code> > > Y a continuación la clase optimizada, que es menos legible > pero funciona casi el doble de rápido: > <code> > 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<w; i++) { > for (var j:Number=0; j<h; 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; > } > </code> > > 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: > <code> > //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); </code> > > 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 -----------------------------------------------------

