web-dev-qa-db-ja.com

PHPで画像の主要な色を検出する

Dribbble.comが画像の主要な色を検出する機能を再現しようとしています。以下の画像では、Dribbble.comのスクリーンショットを見ることができます。スクリーンショットには、左の画像の8つの主要な色が示されています。これが画像の実際のページです http://dribbble.com/shots/528033-Fresh-Easy?list=following

PHPでこれを実行できるようにする必要があります。必要な色が得られたら、データベースに保存して、ページの読み込みごとに処理を実行する必要がないようにします。

画像からこれらの色を取り出す方法に関するいくつかの研究の後、一部の人々は、単にピクセルごとに画像を調べてから、最も多く発生する色を保存すると言いました。他には、もっと多くのことがあり、最も頻繁に存在する色を取得しても望ましい効果が得られないと言う。彼らはあなたが画像/色を量子化する必要があると言います(私はこの時点で迷っています)。

以下の画像のドリブルショットは、同じことを行うJavascriptライブラリです。このページはここで表示できます http://lokeshdhakar.com/projects/color-thief/

そのページのソースを表示すると、quantize.jsという名前のJavascriptファイルがあり、結果は非常に良好です。だから、私はそのJavascriptライブラリが行うことをできることを望んでいますが、PHP and Gd/ImageMagick

enter image description here


PHPで画像の色とカウントを返すこの関数を見つけましたが、結果は上記のJavaScriptバージョンとドリブルの結果とは異なります

/**
 * 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でそのようなタスクを行う方法を知っているかどうか尋ねていますか?おそらくあなたが知っている何かが既に存在するか、私がこれを行うことにより近づくためのヒントをいただければ幸いです

31
JasonDavis

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);
34
Epoc

これは、画像のメインカラーを取得する私の簡単な方法です

$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;
13
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.

これを試してください: 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] = 1816011904761905 0.0151190> 190 [a87830] => 0.014345238095238 [a8c0d8] => 0.011904761904762 [6090c0] => 0.01172619047619 [d89030] => 0.011011904761905 [90a8d8] => 0.0071428571428571 [ffffff] => 0.007023800952095 [08595095951938095] [604830] => 0.0065476190419 ] => 0.005297619047619 [c0d8d8] => 0.0044047619047619 [f0f0ff] => 0.00041666666666667 [181830] => 0.00011904761904762)

別の画像で試してみましたが、信頼できるようです。

1
Juergen

私は、あなたが望むことをすることができる、dominantcolorと呼ばれるImageMagickを備えたUnix bash Shellスクリプトを持っています。 http://www.fmwconcepts.com/imagemagick/index.php のスクリプトWebサイトを参照してください。 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

画像の主要な色を取得するという考えは少し複雑です。これは、たとえば、最も頻繁に現れるピクセルの色が画像内で非常に広く分散しているため、まったく主要な色として認識されないためです。

Color coherence vector のようなアルゴリズムは、色をコヒーレントとインコヒーレント(非常に直感的)にクラスター化し、それらのfalseを破棄するために使用できるため、この問題を克服するのに十分だと思います正の優勢な色。

私はそれが実装するのが簡単なアルゴリズムであると思います、このチュートリアル 画像検索:Color Coherence Vectorは説明します それがどのように動作するかの例でその手順を説明し、さらには matlab 実装も言及されています最後に。

0
v.tmab