Обнаруживать основные цвета в изображении с помощью PHP
Я пытаюсь реплицировать функции, которые Dribbble.com делает с обнаружением преобладающих цветов в изображении. На изображении ниже вы можете увидеть скриншот от Dribbble.com, который показывает 8 преобладающих цветов на изображении слева. Вот фактическая страница на картинке http://dribbble.com/shots/528033-Fresh-Easy?list=following
Мне нужно иметь возможность сделать это на PHP, как только я получу нужные цвета, я сохраню их в базе данных, поэтому обработка не должна запускаться при каждой загрузке страницы.
После некоторых исследований о том, как получить эти цвета из изображения, некоторые люди сказали, что вы просто просматриваете пиксель изображения по пикселям, а затем сохраняете цвета, которые больше всего встречаются. Другие говорят, что есть больше, и что получение цветов, которые существуют наиболее часто, не даст желаемого эффекта. Говорят, вам нужно квантифицировать изображение/цвета (я теряюсь в этой точке).
На рисунке ниже снимок Dribble ниже - это библиотека Javascript, которая делает то же самое, эту страницу можно посмотреть здесь http://lokeshdhakar.com/projects/color-thief/
Просмотр источника этой страницы. Я вижу, что есть файл Javascript с именем quantize.js
, и результаты действительно хороши. Поэтому я надеюсь, что смогу сделать то, что делает библиотека Javascript, но с PHP и GD/ImageMagick
![enter image description here]()
Я нашел эту функцию, которая вернет цвета и подсчет в изображении с PHP, но результаты отличаются от версии Javascript выше и результатов 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)");
}
Итак, я спрашиваю, знает ли кто, как я могу сделать такую задачу с PHP? Возможно, что-то существует уже, что вы знаете или какие-либо советы, чтобы поставить меня на шаг ближе к этому, будет оценено
Ответы
Ответ 1
Вот именно то, что вы ищете в PHP: https://github.com/thephpleague/color-extractor
Пример:
use League\ColorExtractor\ColorExtractor;
use League\ColorExtractor\Palette;
$palette = Palette::fromFilename('some/image.png');
$topEightColors = $palette->getMostUsedColors(8);
Ответ 2
Это мой простой способ получить основной цвет изображения
$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;
Ответ 3
Вам нужно уменьшить масштаб изображения, и вы получите основные цвета изображения. Если вам нужно 4 цвета в поддоне, уменьшите его до 8x8
, 6 цветов примерно до 12x8
и так далее...
imagecopyresized
для уменьшенного изображения, затем проверьте все пиксели и сохраните их в массиве imagecolorat($image,px,py)
Попробуйте это
<?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;
}
?>
Прекрасно подходит для меня.
Ответ 4
На странице, на которую вы ссылались, есть ссылка на исходный код GitHub, поэтому, если вы хотите точно знать, как они работают, вы можете реплицировать свой источник в PHP.
Большая разница между тем, как они это делают и как вы это делаете, заключается в том, что они используют кластеризацию для поиска цвета. Вместо округления цвета при их хранении они сохраняют все необработанные цвета в массиве. Затем они перемещаются по этому массиву, пока не найдут кластер, который имеет самое высокое отношение точек в кластере к количеству цветов в кластере. Центральная точка этого является наиболее распространенным цветом. Затем палитру определяют следующие высшие наборы кластеров с некоторой логикой для предотвращения почти полного перекрытия кластеров.
Ответ 5
Попробуйте это: http://www.coolphptools.com/color_extract
Работает с JPEG и PNG.
И лучше !: нет суеты с композитором, просто 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);
дать вам что-то вроде этого:
Массив ([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)
Я попробовал это с различными изображениями, и это кажется надежным.
Ответ 6
У меня есть сценарий оболочки Unix bash с ImageMagick с именем dominantcolor, который может делать то, что вы хотите. Смотрите мой веб-сайт сценариев на http://www.fmwconcepts.com/imagemagick/index.php. Вы запускаете его из PHP exec(). Смотрите мои указатели для использования на моей домашней странице.
Входные данные:
![enter image description here]()
dominantcolor -n 6 -p all -s save plate.png
count,hexcolor
586,#5ECADC
520,#AFA85D
469,#3C3126
462,#B9C8BB
258,#488A70
205,#B06928
-n 6 - это желаемое количество цветов в квантовании цветов. -p all означает печать всех подсчетов и цветов для полученных 6 цветов. -s save указывает на сохранение образца изображения.
Цвета ниже показаны с преобладающим цветом слева и уменьшением количества цветов вправо согласно списку выше.
![enter image description here]()
Ответ 7
Идея получения преобладающих цветов изображения немного сложна, потому что, например, наиболее частый цвет пикселя может быть настолько широко рассеян в изображении, что он вообще не воспринимается как преобладающий цвет.
Я думаю, что такой алгоритм, как вектор цветовой когерентности, будет достаточно хорош, чтобы преодолеть эту проблему, потому что он группирует цвета в когерентные и некогерентные (что довольно интуитивно понятно), и затем вы можете использовать их, чтобы отбросить эти ложноположительные преобладающие цвета.
Я вижу, что это простой алгоритм для реализации, этот учебник Image Retrieval: Color Coherence Vector описывает его шаги с примерами того, как он работает, и в конце даже упоминается реализация matlab.