J'essaie de reproduire la fonctionnalité utilisée par Dribbble.com pour détecter les couleurs prédominantes dans une image. Dans l'image ci-dessous, vous pouvez voir une capture d'écran de Dribbble.com qui 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 enregistre dans une base de données afin que le traitement ne soit plus nécessaire à chaque chargement de page.
Après des recherches sur la façon de tirer ces couleurs d’une image, certaines personnes ont dit que vous examiniez simplement une image pixel par pixel, puis enregistriez les couleurs les plus fréquentes. D'autres disent qu'il y a plus que cela et que l'obtention des couleurs qui existent le plus souvent ne donnera pas l'effet souhaité. Ils disent que vous devez quantifier l'image/les couleurs (je suis perdu à ce stade).
Dans l'image ci-dessous, la photo ci-dessous montre une bibliothèque Javascript qui fait la 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 existe un fichier Javascript appelé quantize.js
et que les résultats sont vraiment bons. J'espère donc pouvoir faire ce que cette bibliothèque Javascript fait, 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 de la version Javascript ci-dessus et des 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 qu'il existe déjà quelque chose que vous connaissez déjà ou des astuces pour me rapprocher de cette démarche seraient appréciées
Voici exactement ce que vous recherchez 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();
Ceci 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 obtenir 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 puis vérifiez chaque pixel et stockez-les dans le tableau 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 que vous avez liée a un lien vers le code source sur GitHub, donc si vous voulez savoir exactement comment ils vont, vous pouvez répliquer leur source en PHP.
La grande différence entre la façon dont ils le font et comment vous le faites, c'est qu'ils utilisent le clustering pour trouver la couleur. Au lieu d'arrondir la couleur quand ils la stockent, ils stockent toutes les couleurs brutes d'un tableau. Ensuite, ils parcourent ce tableau jusqu'à trouver un cluster qui présente le rapport de points le plus élevé au nombre de couleurs du cluster. Le point central de cette couleur est la couleur la plus commune. La palette est ensuite définie par les ensembles de grappes immédiatement supérieurs, avec une certaine logique pour empêcher un chevauchement quasi complet des grappes.
J'ai un script Unix bash shell avec ImageMagick appelé domincolor qui peut faire ce que vous voulez. Voir le site Web de mes scripts à l’adresse http://www.fmwconcepts.com/imagemagick/index.php . Vous pouvez l'exécuter à partir de PHP exec (). Voir mes pointeurs pour une utilisation sur ma page d'accueil.
Contribution:
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 souhaité de couleurs dans la quantification des couleurs. Le -p tout signifie imprimer tous les comptes et les couleurs pour les 6 couleurs résultantes. Le -s save indique de sauvegarder une image de nuance.
Les couleurs ci-dessous sont indiquées avec la couleur dominante à gauche et les couleurs décroissantes vers la droite, conformément à la liste ci-dessus.
Essayez ceci: http://www.coolphptools.com/color_extract
Fonctionne avec JPEG et PNG.
Et le meilleur !: pas de bêtise avec le compositeur, il suffit de 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 ça:
Tableau ( [3060a8] => 0.55827380952381 [F0a848] => 0.19791666666667 [000000] => 0.069642857142857. [183060] => 0.01797619047619 [4878a8] => 0.016011904761905 [181800] => 0.015119047619048 [A87830] => 0.014345238095238 0.01172619047619 [D89030] => 0.011011904761905 [90a8d8] => 0.0071428571428571 [Ffffff] => 0.0070238095238095 [604830] => 0.00654761904719____. d8d8f0] => 0.005297619047619 [c0d8d8] => 0.0044047619047619 [f0f0ff] => 0.00041666666666667 [181830] => 0.0001190476190462
Je l'ai essayé avec différentes images et cela 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 tellement dispersée dans l'image qu'elle ne serait pas du tout perçue comme une couleur prédominante.
Je pense qu'un algorithme comme Vecteur de cohérence des couleurs sera assez bon pour résoudre ce problème, car il regroupe les couleurs en couleurs cohérentes et incohérentes (ce qui est assez intuitif), et vous pouvez ensuite les utiliser pour supprimer ces couleurs prédominantes faussement positives. .
Je vois que c’est un algorithme facile à implémenter, ce tutoriel Récupération d’images: Color Coherence Vector décrit décrit ses étapes avec des exemples de son fonctionnement. Une implémentation de matlab est également mentionné à la fin.