Laravel 检测肉眼可见的图像中的独特颜色

Laravel 检测肉眼可见的图像中的独特颜色,laravel,algorithm,colors,detection,color-detection,Laravel,Algorithm,Colors,Detection,Color Detection,Aoa 我目前正在做一个项目,遇到了麻烦。实际上,我想要一个算法来检测人眼可以看到的图像中的颜色数量。我在互联网上使用了一些软件包,但它们甚至提供了很小的颜色变化 示例: 下面提供的图像有两种可见颜色,但我使用的软件包显示4种或4种以上的颜色,如果某个软件包为该图像提供了准确的颜色,则该软件包会为具有多种颜色的图像显示错误的计数。 我使用的一些软件包 这不是一个完美的实现(这将是一个缓慢的过程,尤其是在大图像上),但我们可以这样做: $resource = imagecreatefrompn

Aoa

我目前正在做一个项目,遇到了麻烦。实际上,我想要一个算法来检测人眼可以看到的图像中的颜色数量。我在互联网上使用了一些软件包,但它们甚至提供了很小的颜色变化

示例: 下面提供的图像有两种可见颜色,但我使用的软件包显示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;
然后,我们可以将当前像素与
$results
数组中的每个项目进行比较,方法是添加和减去公差,并检查当前通道(红色、绿色和蓝色)是否在以下范围内:

$near_red = ($color['red'] > ($result['red'] - $tolerance)) && ($color['red'] < ($result['red'] + $tolerance));
这个解决方案可能需要很多优化(在有很多独特颜色的大图像上会非常慢),我在这个实现中忽略了alpha通道(如果需要,很容易添加),但希望它对您有用


此实现的最坏情况复杂度为O(n2),如果图像中的每个像素颜色都是唯一的,则会发生这种情况,这将导致我们的
$results
数组包含以前的每个值,因此每次迭代将包含图像中像素数的嵌套循环(或多或少),对于大型图像来说,这将是难以置信的慢。

您可以解释返回的颜色,并查看它们是否在其他颜色的阈值范围内。在这种情况下,您可以对其进行重复数据消除,只留下“肉眼可见”的颜色。大多数软件包都返回像素计数和十六进制值,因此您能否建议我们如何实现上述目标?十六进制值由6个字符组成。前两条代表红色,第二条代表绿色,最后一条代表蓝色。根据这3种颜色,你可以确定每个部分与另一部分的距离。这是因为角落通常有反alised(谷歌,如果你不知道它是什么)像素,此效果的屏幕截图:。所以4可能是准确的。您可以尝试对图像进行像素化以删除这些像素,可能只提取占图像x%以上的颜色,以获得“良好”的足够阅读效果,具体取决于您的使用情况。我认为您需要对“眼睛可见的唯一颜色”进行更正式的定义,因为取决于您如何定义它,结果会有很大的变化。你的代码很好,必须稍微修改一下,但工作良好,结果不是100%,但似乎可以接受。这是一个棘手的问题,因为肉眼可见是一个相当模糊的问题,但祝你好运。当您找到它时,请分享您的最终实现! O(n2)
echo count($results);
O(n2)