web-dev-qa-db-fra.com

Détecter la couleur "moyenne globale" de l'image

J'ai une image jpg.

J'ai besoin de connaître la "moyenne générale" de la couleur de l'image. À première vue, l'histogramme de l'image peut être utilisé (canal RVB).

Au travail, j’utilise principalement JavaScript et PHP (un peu Python) a donc bien accueilli la décision dans ces langues. Il existe peut-être une bibliothèque pour travailler avec des images qui traitent de problèmes similaires.

Je n'ai pas besoin de déterminer dynamiquement la couleur de l'image. Il me suffit d’une seule fois de parcourir l’ensemble du tableau d’images et de déterminer la couleur de chacune d’elles séparément (cette information me sera utile pour une utilisation ultérieure).

44
Kalinin

Vous pouvez utiliser PHP pour obtenir un tableau de la palette de couleurs comme suit:

<?php 
function colorPalette($imageFile, $numColors, $granularity = 5) 
{ 
   $granularity = max(1, abs((int)$granularity)); 
   $colors = array(); 
   $size = @getimagesize($imageFile); 
   if($size === false) 
   { 
      user_error("Unable to get image size data"); 
      return false; 
   } 
   $img = @imagecreatefromjpeg($imageFile);
   // Andres mentioned in the comments the above line only loads jpegs, 
   // and suggests that to load any file type you can use this:
   // $img = @imagecreatefromstring(file_get_contents($imageFile)); 

   if(!$img) 
   { 
      user_error("Unable to open image file"); 
      return false; 
   } 
   for($x = 0; $x < $size[0]; $x += $granularity) 
   { 
      for($y = 0; $y < $size[1]; $y += $granularity) 
      { 
         $thisColor = imagecolorat($img, $x, $y); 
         $rgb = imagecolorsforindex($img, $thisColor); 
         $red = round(round(($rgb['red'] / 0x33)) * 0x33); 
         $green = round(round(($rgb['green'] / 0x33)) * 0x33); 
         $blue = round(round(($rgb['blue'] / 0x33)) * 0x33); 
         $thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue); 
         if(array_key_exists($thisRGB, $colors)) 
         { 
            $colors[$thisRGB]++; 
         } 
         else 
         { 
            $colors[$thisRGB] = 1; 
         } 
      } 
   } 
   arsort($colors); 
   return array_slice(array_keys($colors), 0, $numColors); 
} 
// sample usage: 
$palette = colorPalette('rmnp8.jpg', 10, 4); 
echo "<table>\n"; 
foreach($palette as $color) 
{ 
   echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td></tr>\n"; 
} 
echo "</table>\n";

Ce qui vous donne un tableau dont les valeurs sont plus élevées pour combien de fois cette couleur a été utilisée.

EDIT Un intervenant a demandé comment utiliser ceci sur tous les fichiers d'un répertoire, le voici:

    if ($handle = opendir('./path/to/images')) {

        while (false !== ($file = readdir($handle))) {
           $palette = colorPalette($file, 10, 4);
           echo "<table>\n"; 
           foreach($palette as $color) { 
               echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td></tr>\n"; 
           } 
           echo "</table>\n";
        }
        closedir($handle);
    }

peut ne pas vouloir faire cela sur trop de fichiers, mais c'est votre serveur.

Alternativement, si vous préférez utiliser JavascriptColor-Theif library de Lokesh fait exactement ce que vous recherchez.

70
JKirchartz

Combinant JKirchartz et Alexander Hugestrand, voici la réponse:

 function getAverage($sourceURL){

    $image = imagecreatefromjpeg($sourceURL);
    $scaled = imagescale($image, 1, 1, IMG_BICUBIC); 
    $index = imagecolorat($scaled, 0, 0);
    $rgb = imagecolorsforindex($scaled, $index); 
    $red = round(round(($rgb['red'] / 0x33)) * 0x33); 
    $green = round(round(($rgb['green'] / 0x33)) * 0x33); 
    $blue = round(round(($rgb['blue'] / 0x33)) * 0x33); 
    return sprintf('#%02X%02X%02X', $red, $green, $blue); 
 }

Essayé et testé, retourne une chaîne hexagonale.

4
Johnny Rockex

Une solution plus courte pour une image en vraies couleurs serait de la réduire à une taille de 1x1 pixel et d’échantillonner la couleur à ce pixel:

$ scaled = imagescale ($ img, 1, 1, IMG_BICUBIC); $ meanColor = imagecolorat ($ img, 0, 0);

... mais je n'ai pas testé cela moi-même.

2
$img = glob('img/*');
foreach ($img as $key => $value) {
    $info = getimagesize($value);
    $mime = $info['mime'];
    switch ($mime) {
        case 'image/jpeg':
            $image_create_func = 'imagecreatefromjpeg';
            break;
        case 'image/png':
            $image_create_func = 'imagecreatefrompng';
            break;
        case 'image/gif':
            $image_create_func = 'imagecreatefromgif';
            break;
    }
    $avg = $image_create_func($value);
    list($width, $height) = getimagesize($value);
    $tmp = imagecreatetruecolor(1, 1);
    imagecopyresampled($tmp, $avg, 0, 0, 0, 0, 1, 1, $width, $height);
    $rgb = imagecolorat($tmp, 0, 0);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF;
    echo '<div style="text-align:center; vertical-align: top; display:inline-block; width:100px; height:150px; margin:5px; padding:5px; background-color:rgb('.$r.','.$g.','.$b.');">';
    echo '<img style="width:auto; max-height:100%; max-width: 100%; vertical-align:middle; height:auto; margin-bottom:5px;" src="'.$value.'">';
    echo '</div>';

vous pouvez obtenir la valeur de la couleur moyenne avec $ r, $ g, & $ b rééchantillonner l'image est bien mieux que de la redimensionner! 

2
antoine demacon

Commencez avec PIL. http://www.pythonware.com/products/pil/

Ouvrez l'objet Image. Utilisez la méthode getdata pour obtenir tous les pixels. Faites la moyenne des valeurs que vous récupérez.

Quelque chose comme ça.

Détection de couleur d'image à l'aide de python

1
S.Lott

J'ai créé le package composer qui fournit à la bibliothèque la possibilité de choisir une couleur moyenne de l'image donnée par son chemin.

Vous pouvez l'installer en exécutant la commande suivante dans votre répertoire de projet:

composer require tooleks/php-avg-color-picker

Exemple d'utilisation:

<?php

use Tooleks\Php\AvgColorPicker\Gd\AvgColorPicker;

$imageAvgHexColor = (new AvgColorPicker)->getImageAvgHexByPath('/absolute/path/to/the/image.(jpg|jpeg|png|gif)');

// The `$imageAvgHexColor` variable contains the average color of the given image in HEX format (#fffff).

Voir la documentation .

0
tooleks