2011-09-21 9 views
8

Estoy intentando crear un script que ejecutará programáticamente una imagen y me dirá su color primario.Determinado programáticamente el color legible por el ser humano (por ejemplo, rojo, verde, etc.) de una imagen

Actualmente, el script obtiene el valor RGB de cada píxel. Los compara con reglas predefinidas e intenta contar el número de píxeles de cada color.

Mi problema es que el script es un poco al azar. ¿Alguien sabe de una mejor manera de hacerlo (tal vez usando un sistema diferente de codificación de colores que es más fácil de traducir al inglés) o un conjunto existente de reglas que definen los colores a través de su RGB?

<?php 
$file = "8629.jpg"; 

$colors = array("Red" => array("rel" => true, "r" => 0.65, "g" => 0.09, "b" => 0.25, "var" => 0.3), 
       "Blue" => array("rel" => true, "r" => 0.21, "g" => 0.32, "b" => 0.46, "var" => 0.3), 
       "Green" => array("rel" => true, "r" => 0, "g" => 0.67,"b" => 0.33, "var" => 0.3), 
       "Black" => array("rel" => false, "r" => 0, "g" => 0,"b" => 0, "var" => 30), 
       "White" => array("rel" => false, "r" => 255, "g" => 255,"b" => 255, "var" => 30));     

$total = 0; 

$im = imagecreatefromjpeg($file); 
$size = getimagesize($file); 

if (!$im) { 
    exit("No image found."); 
} 

for ($x = 1; $x <= $size[0]; $x++) { 
    for($y = 1; $y <= $size[1]; $y++) { 
     $rgb = imagecolorat($im, $x, $y); 
     $r = ($rgb >> 16) & 0xFF; 
     $g = ($rgb >> 8) & 0xFF; 
     $b = $rgb & 0xFF; 

     $colorTotal = $r + $g + $b; 

     $rRatio = $r > 0 ? $r/$colorTotal : 0; 
     $gRatio = $g > 0 ? $g/$colorTotal : 0; 
     $bRatio = $b > 0 ? $b/$colorTotal : 0; 

     foreach($colors as $key => $color) { 
      if ($color["rel"]) { 
       if ((($color["r"] - $color["var"]) <= $rRatio && $rRatio <= ($color["r"] + $color["var"])) && 
        (($color["g"] - $color["var"]) <= $gRatio && $gRatio <= ($color["g"] + $color["var"])) && 
        (($color["b"] - $color["var"]) <= $bRatio && $bRatio <= ($color["b"] + $color["var"]))) { 

        $colourCount[$key]++; 
        $total++; 
       } 
      } else { 
       if ((($color["r"] - $color["var"]) <= $r && $r <= ($color["r"] + $color["var"])) && 
        (($color["g"] - $color["var"]) <= $g && $g <= ($color["g"] + $color["var"])) && 
        (($color["b"] - $color["var"]) <= $b && $b <= ($color["b"] + $color["var"]))) { 

        $colourCount[$key]++; 
        $total++; 
       } 
      } 
     } 
    } 
} 

var_dump($colourCount); 

foreach($colourCount as $key => $color) { 
    $colourPrecent[$key] = $color/$total; 
} 

arsort($colourPrecent); 
var_dump($colourPrecent); 

foreach($colourPrecent as $key => $color) { 
    if ($prevVal) { 
     if ($color < ($prevVal - 0.1)) { 
      break; 
     } 
    } 

    $primary[] = $key; 
    $prevVal = $color; 
} 

echo("The primary colours in this image are " . implode(" and ", $primary)); 

?> 
+2

Hmm, interesante. Me temo que mi única contribución es [esta advertencia] (http://www.thedoghousediaries.com/?p=1406) sobre la definición de colores "legibles por humanos". – Widor

+0

Considerando que una imagen de color verdadero podría tener cada píxel como único, no ganará mucho a menos que empiece a "agrupar" colores similares juntos. Quizás sería más simple encoger la imagen a un píxel de 1x1 y descubrir su color predominante. –

+0

RGB parece ser la [opción menos útil del modelo de color aquí] (http://www.wowarea.com/english/help/color.htm). @Widor, seguramente el script tomará un parámetro IsGuy. ;) – bzlm

Respuesta

2

solución fue convertir RGB a HSL según lo sugerido por Herbert. La función para convertir a humano todavía necesita un pequeño ajuste/acabado, pero aquí está:

function hslToHuman($h, $s, $l) { 

$colors = array(); 

// Gray 
if ($s <= 10 && (9 <= $l && $l <= 90)) { 
    $colors[] = "gray"; 
} 

$l_var = $s/16; 

// White 
$white_limit = 93; 
if (($white_limit + $l_var) <= $l && $l <= 100) { 
    $colors[] = "white"; 
} 

// Black 
$black_limit = 9; 
if (0 <= $l && $l <= ($black_limit - $l_var)) { 
    $colors[] = "black"; 
} 

// If we have colorless colors stop here 
if (sizeof($colors) > 0) { 
    return $colors; 
} 

// Red 
if (($h <= 8 || $h >= 346)) { 
    $colors[] = "red"; 
} 

// Orange && Brown 
// TODO 

// Yellow 
if (40 <= $h && $h <= 65) { 
    $colors[] = "yellow"; 
} 

// Green 
if (65 <= $h && $h <= 170) { 
    $colors[] = "green"; 
} 

// Blue 
if (165 <= $h && $h <= 260) { 
    $colors[] = "blue"; 
} 

// Pink && Purple 
// TODO 

return $colors; 
} 
1

bien por lo que tiene una biblioteca de gráficos, debe haber una cosita medio en allí, un promedio de su imagen, tomar cualquier píxel y tadaam estás hecho?

Y la solución más simple encontrado aquí es: cambiar el tamaño de 1x1px, obtener colorat:

Get image color

Después de que es bastante fácil, encontrar un lugar donde una lista detallada de RGB para lectura mecánica (para los colores de ejemplo html humanos), codifíquelo como una matriz y úselo en su secuencia de comandos -> redondee() su r, g, b, vals a la precisión de sus datos y recupere el color.

Debería determinar qué color de granularidad desea e ir desde allí -> encuentre su conjunto de colores con nombre (creo que todos los colores de 8 bits tienen un nombre en alguna parte) y luego reduzca su información rgb a eso - reduciendo la información de color de la imagen antes de leerlo (más rápido) o reduciendo la información de color en el momento de lectura (más flexible en cuanto a la lista de colores

ejemplo básico de algunos recursos legibles rgb-humana:.

http://www.w3schools.com/html/html_colornames.asp

Otros:

http://chir.ag/projects/name-that-color/#2B7C97

http://r0k.us/graphics/SIHwheel.html

+0

La parte difícil en este momento es encontrar esa lista detallada de RGB a legible para humanos. La secuencia de comandos también debe ser un poco más inteligente que el color promedio. Si tengo una imagen que es 50/50 roja/azul, necesito saber que es roja y azul, no me digan que es de color púrpura. – Dan

+0

La lista RGB que puedes encontrar en cualquier parte de la web buscando "colores HTML", obtendrás un subconjunto con una granularidad específica (más que suficiente para lo que parezcas querer) con todos los colores con nombre, agregó un ejemplo. Acerca de sus múltiples colores, puede hacer lo siguiente: cambiar el tamaño a 4x4, colorear por foreach, clasificar y probar si le conviene. si no, prueba una mejor res. –

+0

Terminó usando el espacio de color HSL. Es mucho más fácil definir un color dentro de un rango de tono que tratar de rastrear 3 variables diferentes y decidir de qué color se trata. Gracias por la entrada. – Dan

Cuestiones relacionadas