以编程方式确定图像的人类可读颜色(例如红色、绿色等)
Posted
技术标签:
【中文标题】以编程方式确定图像的人类可读颜色(例如红色、绿色等)【英文标题】:Programmatically determine human readable color (e.g. Red, Green, etc..) of an image 【发布时间】:2011-11-22 00:54:27 【问题描述】:我正在尝试编写一个脚本,该脚本将以编程方式运行图像并告诉我它是原色。
目前脚本获取每个像素的 RGB 值。将它们与预定义的规则进行比较,并尝试计算每种颜色的像素数。
我的问题是脚本有点命中注定。有谁知道这样做的更好方法(可能使用更容易翻译成英文的不同颜色编码系统)或通过其 RGB 定义颜色的现有规则集?
<?php
$file = "8629.jpg";
$colors = array("Red" => array("rel" => true, "r" => 0.65, "g" => 0.09, "b" => 0.25, "var" => 0.3),
"Blue" => array("rel" => true, "r" => 0.21, "g" => 0.32, "b" => 0.46, "var" => 0.3),
"Green" => array("rel" => true, "r" => 0, "g" => 0.67,"b" => 0.33, "var" => 0.3),
"Black" => array("rel" => false, "r" => 0, "g" => 0,"b" => 0, "var" => 30),
"White" => array("rel" => false, "r" => 255, "g" => 255,"b" => 255, "var" => 30));
$total = 0;
$im = imagecreatefromjpeg($file);
$size = getimagesize($file);
if (!$im)
exit("No image found.");
for ($x = 1; $x <= $size[0]; $x++)
for($y = 1; $y <= $size[1]; $y++)
$rgb = imagecolorat($im, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$colorTotal = $r + $g + $b;
$rRatio = $r > 0 ? $r / $colorTotal : 0;
$gRatio = $g > 0 ? $g / $colorTotal : 0;
$bRatio = $b > 0 ? $b / $colorTotal : 0;
foreach($colors as $key => $color)
if ($color["rel"])
if ((($color["r"] - $color["var"]) <= $rRatio && $rRatio <= ($color["r"] + $color["var"])) &&
(($color["g"] - $color["var"]) <= $gRatio && $gRatio <= ($color["g"] + $color["var"])) &&
(($color["b"] - $color["var"]) <= $bRatio && $bRatio <= ($color["b"] + $color["var"])))
$colourCount[$key]++;
$total++;
else
if ((($color["r"] - $color["var"]) <= $r && $r <= ($color["r"] + $color["var"])) &&
(($color["g"] - $color["var"]) <= $g && $g <= ($color["g"] + $color["var"])) &&
(($color["b"] - $color["var"]) <= $b && $b <= ($color["b"] + $color["var"])))
$colourCount[$key]++;
$total++;
var_dump($colourCount);
foreach($colourCount as $key => $color)
$colourPrecent[$key] = $color / $total;
arsort($colourPrecent);
var_dump($colourPrecent);
foreach($colourPrecent as $key => $color)
if ($prevVal)
if ($color < ($prevVal - 0.1))
break;
$primary[] = $key;
$prevVal = $color;
echo("The primary colours in this image are " . implode(" and ", $primary));
?>
【问题讨论】:
嗯,很有趣。恐怕我唯一的贡献是 this warning 关于定义“人类可读”的颜色! 考虑到真彩色图像可能使每个像素都是唯一的,除非您开始将相似的颜色“组合”在一起,否则您不会获得太多收益。也许将图像缩小到 1x1 像素并找出其主要颜色会更简单。 RGB 看起来像 least useful choice of color model here。 @Widor,脚本肯定会采用 IsGuy 参数。 ;) 在我看来HSL 将是最有用的模型,因为您可以将色相与饱和度和亮度分开。 H:0-120 = 红色,120-240 = 绿色,240-360 = 蓝色。 L:0% = 黑色,L:100% S:100% = 白色。 很高兴我能帮助丹。我已经使用各种颜色模型完成了一些工作。 HSL/HSV 是一种比 RGB 更自然的颜色分量思考方式。 HSL 还具有额外的优势,您可以使用它将颜色转换为等效的灰度,甚至计算 相关 和补充颜色。用 RGB 试试。 :-) 【参考方案1】:解决方案是按照 Herbert 的建议将 RGB 转换为 HSL。转换为人类的功能仍然需要一些调整/完成,但这里是:
function hslToHuman($h, $s, $l)
$colors = array();
// Gray
if ($s <= 10 && (9 <= $l && $l <= 90))
$colors[] = "gray";
$l_var = $s / 16;
// White
$white_limit = 93;
if (($white_limit + $l_var) <= $l && $l <= 100)
$colors[] = "white";
// Black
$black_limit = 9;
if (0 <= $l && $l <= ($black_limit - $l_var))
$colors[] = "black";
// If we have colorless colors stop here
if (sizeof($colors) > 0)
return $colors;
// Red
if (($h <= 8 || $h >= 346))
$colors[] = "red";
// Orange && Brown
// TODO
// Yellow
if (40 <= $h && $h <= 65)
$colors[] = "yellow";
// Green
if (65 <= $h && $h <= 170)
$colors[] = "green";
// Blue
if (165 <= $h && $h <= 260)
$colors[] = "blue";
// Pink && Purple
// TODO
return $colors;
【讨论】:
【参考方案2】:好的,所以你有一个图形库,里面一定有一个普通的东西,你平均你的照片,取任何像素,然后就完成了吗?
在这里找到的最简单的解决方案是:resize to 1x1px, get colorat :
Get image color
之后就很容易了,在某个地方找到一个人类可读的详细 rgb 列表(例如 html 颜色),将其编码为一个数组并在你的脚本中使用它 -> round() 你的 r,g,b, vals以您的数据的精度并检索颜色。
您应该确定您想要的颜色粒度并从那里开始 -> 找到您的一组命名颜色(我认为所有 8 位颜色在某处都有一个名称),然后将您的 rgb 信息减少到该值 - 或者通过减少在读取图像之前(更快)或在读取时减少颜色信息(在颜色列表方面更灵活。
一些 rgb 人类可读资源的基本示例:
http://www.w3schools.com/html/html_colornames.asp
其他:
http://chir.ag/projects/name-that-color/#2B7C97
http://r0k.us/graphics/SIHwheel.html
【讨论】:
目前最困难的部分是找到人类可读的 RGB 详细列表。脚本还需要比平均颜色更智能。如果我有一张 50/50 红色/蓝色的图像,我需要知道它是红色和蓝色的,而不是被告知它是紫色的。 您可以通过搜索“HTML 颜色”在网络上的任何地方找到 RGB 列表,您将获得一个具有特定粒度的子集(对于您似乎想要的而言绰绰有余),其中包含所有命名颜色- 添加了一个例子。关于您的多种颜色,您可以执行以下操作:调整大小为 4x4,foreach colorat,排名并测试它是否适合。如果不尝试更好的资源。 最终使用 HSL 颜色空间。在色调范围内定义颜色比尝试跟踪 3 个不同的变量并确定它是什么颜色要容易得多。感谢您的意见。以上是关于以编程方式确定图像的人类可读颜色(例如红色、绿色等)的主要内容,如果未能解决你的问题,请参考以下文章