使用PHP检测图像中的主要颜色
image-processing
imagemagick
php
4
0

我正在尝试复制Dribbble.com在检测图像中主要颜色时所做的功能。在下面的图像中,您可以看到Dribbble.com的屏幕截图,该屏幕截图在左侧的图像中显示了8种主要颜色。这是图片中的实际页面http://dribbble.com/shots/528033-Fresh-Easy?list=following

我需要能够在PHP中执行此操作,一旦获得所需的颜色,便将其保存到数据库中,因此无需在每次页面加载时都运行该处理。

在研究了如何从图像中获取这些颜色之后,有人说您只是简单地逐像素检查图像,然后保存出现次数最多的颜色。有人说还有更多的东西,而获得最常出现的颜色不会产生想要的效果。他们说您需要量化图像/颜色(这时我迷路了)。

在下面的Dribble快照下的图像中,是一个做同样事情的Javascript库,可以在这里查看该页面http://lokeshdhakar.com/projects/color-thief/

查看该页面的源代码,我可以看到有一个名为quantize.js的JavaScript文件,结果确实很好。所以我希望能够使用PHP和GD / ImageMagick来实现该Javascript库的功能

在此处输入图片说明


我发现此函数将返回颜色并使用PHP在Image中进行计数,但结果与上述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来完成这样的任务?可能您已经知道了一些东西,或者有任何提示使我更进一步地做到这一点

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

您需要按比例缩小图片,您将获得图片的主要颜色。如果您需要在托盘中使用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;

}
?>

对我来说很完美。

收藏
评论

链接到的页面具有指向GitHub上的源代码的链接,因此,如果您想确切了解他们的工作方式,可以在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;
收藏
评论

这正是您在PHP中寻找的东西: https : //github.com/thephpleague/color-extractor

范例:

use League\ColorExtractor\Palette;

$palette = Palette::fromFilename('some/image.png');

$topEightColors = $palette->getMostUsedColors(8);
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号