Détecter les couleurs principales dans une image avec PHP
J'essaie de reproduire la fonctionnalité qui Dribbble.com fait avec la détection des couleurs prédominantes dans une Image. Dans l'image ci-dessous, vous pouvez voir une capture d'écran de Dribbble.com cela montre les 8 couleurs prédominantes dans l'image à gauche. Voici la page réelle dans l'image http://dribbble.com/shots/528033-Fresh-Easy?list=following
Je dois pouvoir le faire en PHP, Une fois que j'aurai les couleurs dont j'ai besoin, je les sauvegarderai dans une base de données afin que le traitement n'ait pas besoin à exécuter sur chaque chargement de page.
Après quelques recherches sur la façon d'obtenir ces couleurs dans une Image, certaines personnes ont dit que vous simplement examiner une image pixel par pixel, puis enregistrez les couleurs qui se produisent le plus. D'autres disent qu'il y a plus à cela et que l'obtention des couleurs qui existent les plus fréquentes ne donnera pas l'effet désiré. Ils disent que vous devez quantifier l'image / les couleurs (je suis perdu à ce stade).
Dans l'image ci-dessous, le tir de Dribble ci-dessous est une bibliothèque Javascript qui fait le même chose, cette page peut être consultée ici http://lokeshdhakar.com/projects/color-thief/
En regardant la source de cette page, je peux voir qu'il y a un fichier Javascript nommé quantize.js
et les résultats sont vraiment bons. J'espère donc pouvoir faire ce que fait cette bibliothèque Javascript mais avec PHP et GD / ImageMagick
J'avais trouvé cette fonction qui retournera les couleurs et comptera dans une Image avec PHP mais les résultats sont différents du Javascript version ci-dessus et les résultats de Dribble
/**
* Returns the colors of the image in an array, ordered in descending order, where the keys are the colors, and the values are the count of the color.
*
* @return array
*/
function Get_Color()
{
if (isset($this->image))
{
$PREVIEW_WIDTH = 150; //WE HAVE TO RESIZE THE IMAGE, BECAUSE WE ONLY NEED THE MOST SIGNIFICANT COLORS.
$PREVIEW_HEIGHT = 150;
$size = GetImageSize($this->image);
$scale=1;
if ($size[0]>0)
$scale = min($PREVIEW_WIDTH/$size[0], $PREVIEW_HEIGHT/$size[1]);
if ($scale < 1)
{
$width = floor($scale*$size[0]);
$height = floor($scale*$size[1]);
}
else
{
$width = $size[0];
$height = $size[1];
}
$image_resized = imagecreatetruecolor($width, $height);
if ($size[2]==1)
$image_orig=imagecreatefromgif($this->image);
if ($size[2]==2)
$image_orig=imagecreatefromjpeg($this->image);
if ($size[2]==3)
$image_orig=imagecreatefrompng($this->image);
imagecopyresampled($image_resized, $image_orig, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); //WE NEED NEAREST NEIGHBOR RESIZING, BECAUSE IT DOESN'T ALTER THE COLORS
$im = $image_resized;
$imgWidth = imagesx($im);
$imgHeight = imagesy($im);
for ($y=0; $y < $imgHeight; $y++)
{
for ($x=0; $x < $imgWidth; $x++)
{
$index = imagecolorat($im,$x,$y);
$Colors = imagecolorsforindex($im,$index);
$Colors['red']=intval((($Colors['red'])+15)/32)*32; //ROUND THE COLORS, TO REDUCE THE NUMBER OF COLORS, SO THE WON'T BE ANY NEARLY DUPLICATE COLORS!
$Colors['green']=intval((($Colors['green'])+15)/32)*32;
$Colors['blue']=intval((($Colors['blue'])+15)/32)*32;
if ($Colors['red']>=256)
$Colors['red']=240;
if ($Colors['green']>=256)
$Colors['green']=240;
if ($Colors['blue']>=256)
$Colors['blue']=240;
$hexarray[]=substr("0".dechex($Colors['red']),-2).substr("0".dechex($Colors['green']),-2).substr("0".dechex($Colors['blue']),-2);
}
}
$hexarray=array_count_values($hexarray);
natsort($hexarray);
$hexarray=array_reverse($hexarray,true);
return $hexarray;
}
else die("You must enter a filename! ($image parameter)");
}
Donc je demande si quelqu'un sait comment je peux faire une telle tâche avec PHP? Peut-être quelque chose existe déjà que vous connaissez ou des conseils pour me mettre un peu plus près de faire cela serait apprécié
7 réponses
Voici exactement ce que vous cherchez en PHP: https://github.com/thephpleague/color-extractor
Exemple :
require 'vendor/autoload.php';
use League\ColorExtractor\Client as ColorExtractor;
$client = new ColorExtractor;
$image = $client->loadPng('./some/image.png');
// Get the most used color hexadecimal codes from image.png
$palette = $image->extract();
C'est ma méthode simple pour obtenir la couleur principale d'une image
<?php
$image=imagecreatefromjpeg('image.jpg');
$thumb=imagecreatetruecolor(1,1); imagecopyresampled($thumb,$image,0,0,0,0,1,1,imagesx($image),imagesy($image));
$mainColor=strtoupper(dechex(imagecolorat($thumb,0,0)));
echo $mainColor;
?>
Vous devez réduire l'image et vous obtiendrez les couleurs principales de l'image. Si vous avez besoin de 4 couleurs dans la palette, réduisez-la à environ 8x8
, 6 couleurs à environ 12x8
et ainsi de suite...
imagecopyresized
pour une image réduite, vérifiez tous les pixels et stockez-les dans array imagecolorat($image,px,py)
Essayez ceci
<?php
// EXAMPLE PICTURE
$url='https://www.nordoff-robbins.org.uk/sites/default/files/google.jpg';
//var_dump(getColorPallet($url));
echoColors(getColorPallet($url));
function echoColors($pallet){ // OUTPUT COLORSBAR
foreach ($pallet as $key=>$val)
echo '<div style="display:inline-block;width:50px;height:20px;background:#'.$val.'"> </div>';
}
function getColorPallet($imageURL, $palletSize=[16,8]){ // GET PALLET FROM IMAGE PLAY WITH INPUT PALLET SIZE
// SIMPLE CHECK INPUT VALUES
if(!$imageURL) return false;
// IN THIS EXEMPLE WE CREATE PALLET FROM JPG IMAGE
$img = imagecreatefromjpeg($imageURL);
// SCALE DOWN IMAGE
$imgSizes=getimagesize($imageURL);
$resizedImg=imagecreatetruecolor($palletSize[0],$palletSize[1]);
imagecopyresized($resizedImg, $img , 0, 0 , 0, 0, $palletSize[0], $palletSize[1], $imgSizes[0], $imgSizes[1]);
imagedestroy($img);
//CHECK IMAGE
/*header("Content-type: image/png");
imagepng($resizedImg);
die();*/
//GET COLORS IN ARRAY
$colors=[];
for($i=0;$i<$palletSize[1];$i++)
for($j=0;$j<$palletSize[0];$j++)
$colors[]=dechex(imagecolorat($resizedImg,$j,$i));
imagedestroy($resizedImg);
//REMOVE DUPLICATES
$colors= array_unique($colors);
return $colors;
}
?>
Fonctionne parfaitement pour moi.
La page à laquelle vous avez lié a un lien vers le code source sur GitHub, donc si vous voulez savoir exactement comment ils font, vous pouvez répliquer leur source en PHP.
La grande différence entre la façon dont ils le font et la façon dont vous le faites, c'est qu'ils utilisent le clustering pour trouver la couleur. Au lieu d'arrondir la couleur lorsqu'ils la stockent, ils stockent toutes les couleurs brutes dans un tableau. Ensuite, ils parcourent ce tableau jusqu'à ce qu'ils trouvent un cluster qui a le ratio le plus élevé de points du cluster nombre de couleurs dans le cluster. Le point central de ceci est la couleur la plus commune. La palette est ensuite définie par les ensembles de clusters les plus élevés, avec une certaine logique pour éviter un chevauchement presque complet des clusters.
Essayez ceci: http://www.coolphptools.com/color_extract
Fonctionne avec JPEG et PNG.
Et le meilleur!: pas d'agitation avec composer, juste require_once
require_once 'colorextract/colors.inc.php';
$ex=new GetMostCommonColors();
$num_results=20;
$reduce_brightness=1;
$reduce_gradients=1;
$delta=24;
$colors=$ex->Get_Color( 'image.png', $num_results, $reduce_brightness, $reduce_gradients, $delta);
print_r($colors);
Vous Donner quelque chose comme ceci:
Tableau ( [3060a8] = > 0,55827380952381 [f0a848] = > 0.19791666666667 [000000] => 0.069642857142857 [483018] => 0.02047619047619 [786018] => 0.01827380952381 [183060] => 0.01797619047619 [4878a8] = > 0,016011904761905 [181800] => 0.015119047619048 [a87830] = > 0,014345238095238 [a8c0d8] = > 0,011904761904762 [6090c0] = > 0,01172619047619 [d89030] = > 0,011011904761905 [90a8d8] = > 0,0071428571428571 [ffffff] = > 0,0070238095238095 [604830] => 0.006547619047619 [f0f0f0] = > 0,0063095238095238 [d8d8f0] = > 0,005297619047619 [c0d8d8] = > 0,0044047619047619 [f0f0ff] = > 0,00041666666666667 [181830] => 0.00011904761904762 )
J'ai essayé avec des images différentes, et il semble fiable.
L'idée d'obtenir les couleurs prédominantes de l'image est un peu délicate, car par exemple la couleur de pixel la plus fréquente pourrait être si largement dispersée dans l'image qu'elle n'est pas perçue comme une couleur prédominante du tout.
Je pense qu'un algorithme comme color coherence vector sera assez bon pour surmonter ce problème, car il regroupe les couleurs en cohérence et incohérente (ce qui est assez intuitif), et ensuite vous pouvez les utiliser pour jeter ces faux positifs couleurs prédominantes.
Je vois que c'est un algorithme facile à implémenter, ce tutoriel récupération D'Image: Color Coherence Vector décrit décrit ses étapes avec des exemples de comment cela fonctionne et il y a même une implémentation matlab mentionnée à la fin de celui-ci.
J'ai un script shell Unix bash avec ImageMagick appelé dominantcolor qui peut faire ce que vous voulez. Voir le site Web de mes scripts à http://www.fmwconcepts.com/imagemagick/index.php . vous l'exécutez à partir de PHP exec (). Voir mes pointeurs pour une utilisation sur ma page d'accueil.
Entrée:
dominantcolor -n 6 -p all -s save plate.png
count,hexcolor
586,#5ECADC
520,#AFA85D
469,#3C3126
462,#B9C8BB
258,#488A70
205,#B06928
Le-N 6 est le nombre de couleurs souhaité dans la quantification des couleurs. Le-P all signifie imprimer tous les comptes et les couleurs pour les 6 couleurs résultantes. Le-s enregistrer accuse d'enregistrer une image d'échantillon.
Les couleurs ci-dessous sont affichées avec la couleur dominante sur la gauche et les couleurs de comptage décroissantes vers la droite selon la liste ci-dessus.