it-swarm.com.ru

Определить основные цвета в изображении с PHP

Я пытаюсь повторить функциональность, которую Dribbble.com делает с обнаружением преобладающих цветов в изображении. На изображении ниже вы можете увидеть скриншот с Dribbble.com, который показывает 8 преобладающих цветов на изображении слева. Вот фактическая страница в изображении http://dribbble.com/shots/528033-Fresh-Easy?list=following

Я должен быть в состоянии сделать это в PHP, как только я получу нужные мне цвета, я сохраню их в базе данных, чтобы не нужно было выполнять обработку при каждой загрузке страницы. 

После некоторых исследований о том, как получить эти цвета из изображения, некоторые люди сказали, что вы просто исследуете изображение попиксельно, а затем сохраняете цвета, которые встречаются чаще всего. Другие говорят, что это еще не все, и что получение наиболее часто встречающихся цветов не даст желаемого эффекта. Они говорят, что вам нужно квантовать изображение/цвета (я потерялся в этой точке).

На изображении ниже Dribble shot ниже представлена ​​библиотека 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? Возможно, уже есть что-то, о чем вы знаете, или какие-либо советы, которые позволят мне сделать шаг ближе к этому, будут оценены

27
JasonDavis

Вот именно то, что вы ищете в PHP: https://github.com/thephpleague/color-extractor

Пример :

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();
32
Epoc

Это мой простой способ получить основной цвет изображения

<?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;

?>
12
Emanuel Cuccato

Вам нужно уменьшить изображение, и вы получите основные цвета изображения. Если вам нужно 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;

}
?>

Работает идеально для меня.

6
Dust999

На странице, на которую вы ссылаетесь, есть ссылка на исходный код на GitHub, поэтому, если вы хотите точно знать, как они работают, вы можете скопировать их исходный код на PHP.

Большая разница между тем, как они это делают, и тем, как вы это делаете, заключается в том, что они используют кластеризацию, чтобы найти цвет. Вместо округления цвета при сохранении они сохраняют все необработанные цвета в массиве. Затем они перебирают этот массив, пока не найдут кластер, который имеет самое высокое отношение точек в кластере к количеству цветов в кластере. Центром этого является самый распространенный цвет. Затем палитра определяется следующими самыми высокими наборами кластеров, с некоторой логикой, чтобы предотвратить почти полное перекрытие кластеров.

3
Alex N.

У меня есть сценарий Unix bash Shell с 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

1
fmw42

Попробуйте это: 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);

дать вам что-то вроде этого:

Array ( [3060a8] => 0,55827380952381 [F0a848] => 0,19791666666667 [000000] => 0,069642857142857 [483018] => 0,02047619047619 [786018] => 0,018273,89 [183060] => 0,01797619047619 [4878a8] => 0,016011904761905 [181800] => 0,015119047619048 [A87830] => 0,014345238095238 [A8c0d8] => 0,011904761904762. 0,01172619047619 [D89030] => 0,011011904761905 [90a8d8] => 0,0071428571428571 [Ffffff] => 0,0070238095238095 [604830] => 0,006547619047619 [F08080]. d8d8f0] => 0,005297619047619 [c0d8d8] => 0,0044047619047619 [f0f0ff] => 0,00041666666666667 [181830] => 0,00011904761904762)

Я попробовал это с различными изображениями, и это кажется надежным.

0
Juergen

Идея получения преобладающих цветов изображения немного сложна, потому что, например, наиболее частый цвет пикселя может быть настолько широко рассеян в изображении, что он вообще не воспринимается как преобладающий цвет. 

Я думаю, что такой алгоритм, как вектор цветовой когерентности будет достаточно хорош для преодоления этой проблемы, потому что он группирует цвета в когерентные и некогерентные (что довольно интуитивно понятно), и затем вы можете использовать их, чтобы отбросить эти ложноположительные преобладающие цвета , 

Я вижу, что это простой алгоритм для реализации, этот урок Извлечение изображения: Цветовой вектор когерентности описывает описывает его шаги с примерами того, как он работает, и в конце даже упоминается реализация matlab .

0
v.tmab