通过颜色对1万张图像进行排序

5

我有10,000张图片需要按颜色分类,以便制作成印刷品。

我已经做了一些工作。现在我已经计算出它们的平均颜色,所以我有两个目录:一个是所有原始图像的目录(original_images/),另一个是名字相同的jpeg文件,它们的颜色是平均的(averages/)。

接下来,我使用PHP对这些平均图像进行排序:

// $images is an array with all the filenames.
$sorted_images = array();
$loop_limit = count($images);
for($i = 0; $i < $loop_limit; $i++) {
    $image = imagecreatefromjpeg("averages/" . $images[$i]);
    $rgb = imagecolorat($image, 50, 50);
    imagedestroy($image);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF;
    $hsv = rgb_to_hsv($r, $g, $b); // function to convert rgb to Hue/Sat/Value
    $h = (string) $hsv['H'];
    if(isset($sorted_h[$h])) {
        $duplicates++;
        echo("oh no! " . $h . " is a dupe! found " . $duplicates . " duplicates so far.<br>");
    }
    $sorted_h[$h] = $images[$i];
}

// sort the array by key:
ksort($sorted_images, SORT_NUMERIC);

编辑 问题在于键$h的范围似乎从-0.1666666667到大约1。我的直觉是重复值的机会非常小,但实际上有超过6000个重复的键。我尝试将$h的值转换为字符串,因为我想也许数组键是四舍五入的?

但这种方法行不通。这是将RGB转换为HSV的函数,我在某个地方找到它,没有任何文档...

function RGB_TO_HSV ($R, $G, $B) { 
    $HSV = array();

    $var_R = ($R / 255);
    $var_G = ($G / 255);
    $var_B = ($B / 255);

    $var_Min = min($var_R, $var_G, $var_B);
    $var_Max = max($var_R, $var_G, $var_B);
    $del_Max = $var_Max - $var_Min;

    $V = $var_Max;

    if ($del_Max == 0)
    {
        $H = 0;
        $S = 0;
    }
    else
    {
        $S = $del_Max / $var_Max;

        $del_R = ( ( ( $max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
        $del_G = ( ( ( $max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
        $del_B = ( ( ( $max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;

        if ($var_R == $var_Max) $H = $del_B - $del_G;
        else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B;
        else if ($var_B == $var_Max) $H = ( 2 / 3 ) + $del_G - $del_R;

        if (H<0) $H++;
        if (H>1) $H--;
    }

    $HSV['H'] = $H;
    $HSV['S'] = $S;
    $HSV['V'] = $V;

    return $HSV;
}

现在的问题是:

  1. rgb_to_hsv()函数是否正确?
  2. 如何确保在数组中不会覆盖键,但值(近似)保持不变?例如;如果两个图像具有$h-value$为0.01111111111,则将第二个图像推送到数组中时,它的键应该是0.01111111112吗?

(旧编辑:)
编辑: 我已经将rename()更改为copy(),这样每次出错时我就不必重新上传10,000张图片;-)。我还使用了ini_set("max_execution_time", 300);将最大执行时间从60增加到300,通过添加imagedestroy($image)来减少内存使用量,并通过将$i < count($images)更改为$loop_limit = count($images)来改进for循环。

编辑2:好的,我发现了一个问题。图像的$h$(色相)值偶尔会相同。因此,在数组中使用sorted_images[$h] = $images[$i]会覆盖该键在数组中的值。实际上;竟然有超过6000个重复值...我应该如何修复它,而不会太多地影响$h-value$?


2
在迭代完成后不要忘记使用 imagedestroy($image); - Alain Tiemblo
1
for 循环中的 count($images) 是有史以来最糟糕的做法! - Shiplu Mokaddim
2个回答

1

你尝试过启用错误信息吗?

error_reporting(E_ALL);
ini_set('display_errors', 1);

关于本地与主值。'local'表示当前运行的脚本使用300秒的超时时间。'master'适用于所有其他请求(除非明确修改)。
Cron可能是一种方法,但我认为这不应该每X秒/分钟/小时执行多次?您可以简单地自己使用命令行来完成此操作。在此处查看更多信息:http://www.php.net/manual/en/features.commandline.usage.php 鉴于脚本的工作方式,最有可能是以下问题之一:
内存限制不够高。启用错误后应该会给出PHP错误。 执行时间不够长。启用错误后应该会给出PHP错误。
使用init_set方法增加两者,如果您“只是”想运行脚本,请将超时设置为0秒,并将内存限制设置得尽可能高。如果您想真正了解确切的原因,您可以考虑查找“xdebug”,以查看是否存在任何内存泄漏或哪些命令需要执行最长时间。从代码上看,我假设复制命令需要花费一些时间才能执行(超过10000次迭代后1毫秒以上,这是很多的)。
如果无法修改这些值,或者您只是想尝试使用有限资源处理高内存、长执行时间脚本,请尝试将脚本重写为分批执行重命名,并设置一个 cron 每 X 分钟执行一次脚本(当所有图像都完成后,只需删除 cron)。
祝好运 :)

谢谢 :-)。实际上我正在接近问题所在。我修复了脚本以减少内存的使用,这总是好事。但事实上,我开始认为问题出在数组本身上。由于某种原因,许多数组键值被覆盖了。我将更新问题进一步概述此事。 - Rein
1
色调键,特别是在处理10000张图片时可能不够唯一。实际上,将色调键包含所有该色调的图像数组,而不仅仅是单个图像,可能更加安全可靠(简单来说:sorted_images[$h][] = $images[$i];)。但你需要改变复制循环。 - Tjirp

1

max_execution_time 设置为 60(主服务器)和 300(本地)。我不确定使用哪一个。 - Rein
1
@ReinoudSchuijers 你应该在cron上运行这样的作业。另请参阅我对问题的评论。它还将消耗大量时间。 - Shiplu Mokaddim
好的,我对cron完全没有经验。通过一番谷歌搜索,我得出的结论是它很难入手。你有什么好的起点吗? - Rein
@ReinoudSchuijers 你只需要看一下它(使用ini_get)。 - Louis Huppenbauer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接