检测肉眼可见的图像中的独特颜色
Detect unique colors in an image visible to eye
奥阿,
我目前正在做一个项目,stuck.Actually我想要一个算法来检测图像中人眼可见的颜色数量。我在互联网上使用了一些软件包,但它们甚至提供了很小的颜色变化。
示例:
下面提供的图像有两种可见颜色,但我使用的包装显示 4 种或超过 4 种,如果某些包装为该图像提供准确的颜色,而不是显示具有多种颜色的图像的错误计数。
我用过的一些包
这不是一个完美的实现(这会很慢,尤其是在大图像上),但我们可以这样做:
$resource = imagecreatefrompng("test.png"); // Load our image (use imagecreatefromjpeg if using jpeg)
$width = imagesx($resource); // Get image width
$height = imagesy($resource); // Get image height
$results = []; // Create empty array to hold our "unique" color results
$tolerance = 5; // The amount of variation allowed to consider a color the same
// Loop each pixel in the image
for($x = 0; $x < $width; $x++) {
for($y = 0; $y < $height; $y++) {
$add = true;
$color_index = imagecolorat($resource, $x, $y);
$color = imagecolorsforindex($resource, $color_index); // Get the color as an array
// Push the first pixel into our results so we have something to start the comparison against
if (count($results) == 0){
$results[] = $color;
} else {
// Compare the current colour to our results using the tolerance
foreach ($results as $i => &$result):
$near_red = ($color['red'] > ($result['red'] - $tolerance)) && ($color['red'] < ($result['red'] + $tolerance));
$near_green = ($color['green'] > ($result['green'] - $tolerance)) && ($color['green'] < ($result['green'] + $tolerance));
$near_blue = ($color['blue'] > ($result['blue'] - $tolerance)) && ($color['blue'] < ($result['blue'] + $tolerance));
if ($near_red && $near_green && $near_blue){
// This colour is similar to another result
$add = false;
}
if (!$add){
break;
}
endforeach;
if ($add){
$results[] = $color;
}
}
}
}
// Output the unique colors visually. You would probably just count($results) here
foreach($results as $item):
$color = $item['red'] . "," . $item['green'] . "," . $item['blue'] . "," . "1";
echo "<div style='width: 10px; height: 10px; background-color: rgba($color); display: inline-block;'></div>";
endforeach;
使用此图像(包含 8 种独特的颜色):
和 75
的公差,我们得到以下 4 种颜色的输出:
公差为 10
我们得到以下 8 种颜色:
当我们循环图像中的每个像素时,我们得到 RGBA 格式的颜色值,例如:
[
"red" => 255,
"green" => 255,
"blue" => 255,
"alpha" => 255,
]
然后我们可以通过添加和减去公差并检查当前通道(红色、绿色和蓝色)是否落在范围内来将当前像素与 $results
数组中的每个项目进行比较:
$near_red = ($color['red'] > ($result['red'] - $tolerance)) && ($color['red'] < ($result['red'] + $tolerance));
例如,如果我们当前像素的红色值为 50,容差为 5,我们将检查 $results
中是否有一个项目的红色值在 45 到 55 之间。我们做同样的事情绿色和蓝色。如果所有 3 个通道都在范围内,则意味着我们的 $results
中已经有相似的颜色,因此我们不会将当前像素颜色添加到 $results
数组中。
较大的 $tolerance
值将匹配不太相似的颜色。 0
的 $tolerance
值将检查完全匹配并在我们的 $results
中产生更独特的颜色。
如果不存在类似值,我们将当前像素 RGBA 值推送到我们的 $results
数组。
代码完成后 运行,$results
数组将包含 "unique" 颜色。我们可以这样计算颜色:
echo count($results);
这个解决方案可以使用大量优化(在具有许多独特颜色的大图像上它会非常慢),并且我在这个实现中忽略了 alpha 通道(如果需要很容易添加)但希望它对你有用。
此实现的最坏情况复杂度是
O(n2)
如果图像中的每个像素颜色都是唯一的,这将导致我们的 $results
数组包含每个先前的值,因此每次迭代都会包含图像中像素数的嵌套循环(或多或少),这对于大图像来说会非常慢。
奥阿,
我目前正在做一个项目,stuck.Actually我想要一个算法来检测图像中人眼可见的颜色数量。我在互联网上使用了一些软件包,但它们甚至提供了很小的颜色变化。
示例:
下面提供的图像有两种可见颜色,但我使用的包装显示 4 种或超过 4 种,如果某些包装为该图像提供准确的颜色,而不是显示具有多种颜色的图像的错误计数。
我用过的一些包
这不是一个完美的实现(这会很慢,尤其是在大图像上),但我们可以这样做:
$resource = imagecreatefrompng("test.png"); // Load our image (use imagecreatefromjpeg if using jpeg)
$width = imagesx($resource); // Get image width
$height = imagesy($resource); // Get image height
$results = []; // Create empty array to hold our "unique" color results
$tolerance = 5; // The amount of variation allowed to consider a color the same
// Loop each pixel in the image
for($x = 0; $x < $width; $x++) {
for($y = 0; $y < $height; $y++) {
$add = true;
$color_index = imagecolorat($resource, $x, $y);
$color = imagecolorsforindex($resource, $color_index); // Get the color as an array
// Push the first pixel into our results so we have something to start the comparison against
if (count($results) == 0){
$results[] = $color;
} else {
// Compare the current colour to our results using the tolerance
foreach ($results as $i => &$result):
$near_red = ($color['red'] > ($result['red'] - $tolerance)) && ($color['red'] < ($result['red'] + $tolerance));
$near_green = ($color['green'] > ($result['green'] - $tolerance)) && ($color['green'] < ($result['green'] + $tolerance));
$near_blue = ($color['blue'] > ($result['blue'] - $tolerance)) && ($color['blue'] < ($result['blue'] + $tolerance));
if ($near_red && $near_green && $near_blue){
// This colour is similar to another result
$add = false;
}
if (!$add){
break;
}
endforeach;
if ($add){
$results[] = $color;
}
}
}
}
// Output the unique colors visually. You would probably just count($results) here
foreach($results as $item):
$color = $item['red'] . "," . $item['green'] . "," . $item['blue'] . "," . "1";
echo "<div style='width: 10px; height: 10px; background-color: rgba($color); display: inline-block;'></div>";
endforeach;
使用此图像(包含 8 种独特的颜色):
和 75
的公差,我们得到以下 4 种颜色的输出:
公差为 10
我们得到以下 8 种颜色:
当我们循环图像中的每个像素时,我们得到 RGBA 格式的颜色值,例如:
[
"red" => 255,
"green" => 255,
"blue" => 255,
"alpha" => 255,
]
然后我们可以通过添加和减去公差并检查当前通道(红色、绿色和蓝色)是否落在范围内来将当前像素与 $results
数组中的每个项目进行比较:
$near_red = ($color['red'] > ($result['red'] - $tolerance)) && ($color['red'] < ($result['red'] + $tolerance));
例如,如果我们当前像素的红色值为 50,容差为 5,我们将检查 $results
中是否有一个项目的红色值在 45 到 55 之间。我们做同样的事情绿色和蓝色。如果所有 3 个通道都在范围内,则意味着我们的 $results
中已经有相似的颜色,因此我们不会将当前像素颜色添加到 $results
数组中。
较大的 $tolerance
值将匹配不太相似的颜色。 0
的 $tolerance
值将检查完全匹配并在我们的 $results
中产生更独特的颜色。
如果不存在类似值,我们将当前像素 RGBA 值推送到我们的 $results
数组。
代码完成后 运行,$results
数组将包含 "unique" 颜色。我们可以这样计算颜色:
echo count($results);
这个解决方案可以使用大量优化(在具有许多独特颜色的大图像上它会非常慢),并且我在这个实现中忽略了 alpha 通道(如果需要很容易添加)但希望它对你有用。
此实现的最坏情况复杂度是
O(n2)如果图像中的每个像素颜色都是唯一的,这将导致我们的
$results
数组包含每个先前的值,因此每次迭代都会包含图像中像素数的嵌套循环(或多或少),这对于大图像来说会非常慢。