首页 > php图像处理 > 利用k-means聚类算法识别图片主色调

利用k-means聚类算法识别图片主色调

由于使用php来写图片主色调识别功能太麻烦了,所以我给大家介绍利用利用k-means聚类算法识别图片主色调方法.

识别图片主色调这个,网上貌似有几种方法,不过最准确,最优雅的解决方案还是利用聚类算法来做.

直接上代码,不过,我测试结果表示,用PHP来做,效率不佳,PHP不适合做这种大规模运算,用nodejs做效率可以高出100倍左右,代码如下:

<?php
$start = microtime(TRUE);
main();
function main($img = 'colors_files/T1OX3eXldXXXcqfYM._111424.jpg') {
    list($width, $height, $mime_code) = getimagesize($img);
    //开源代码phprm.com
    $im = null;
    $point = array();
    switch ($mime_code) {
            // jpg
            
        case 2:
            $im = imagecreatefromjpeg($img);
            break;
            // png
            
        case 3:
        default:
            exit('擦 ,什么图像?解析不了啊');
    }
    $new_width = 100;
    $new_height = 100;
    $pixel = imagecreatetruecolor($new_width, $new_height);
    imagecopyresampled($pixel, $im, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
    run_time();
    $i = $new_width;
    while ($i–) {
        // reset高度
        $k = $new_height;
        while ($k–) {
            $rgb = ImageColorAt($im, $i, $k);
            array_push($point, array(
                'r' => ($rgb >> 16) & 0xFF,
                'g' => ($rgb >> 8) & 0xFF,
                'b' => $rgb & 0xFF
            ));
        }
    }
    imagedestroy($im);
    imagedestroy($pixel);
    run_time();
    $color = kmeans($point);
    run_time();
    foreach ($color as $key => $value) & nbsp; {
        echo '<br><span style="background-color:' . RGBToHex($value[0]) . '" >' . RGBToHex($value[0]) . '</span>';
    }
}
function run_time() {
    global $start;
    echo '<br/>消耗:', microtime(TRUE) – $start;
}
function kmeans($point = array() , $k = 3, $min_diff = 1) {
    global $ii;
    $point_len = count($point);
    $clusters = array();
    $cache = array();
    for ($i = 0; $i < 256; $i++) {
        $cache[$i] = $i * $i;
    }
    // 随机生成k值
    $i = $k;
    $index = 0;
    while ($i–) {
        $index = mt_rand(1, $point_len - 100);
        array_push($clusters, array(
            $point[$index],
            array(
                $point[$index]
            )
        ));
    }
    run_time();
    $point_list = array();
    $run_num = 0;
    while (TRUE) {
        foreach ($point as $value) {
            $smallest_distance = 10000000;
            // 求出距离最小的点
            // index用于保存point最靠近的k值
            $index = 0;
            $i = $k;
            while ($i–) {
                $distance = 0;
                foreach ($value as $key => $p1) {&nbsp;
                    if ($p1 > $clusters[$i][0][$key]) {
                        $distance+= $cache[$p1 - $clusters[$i][0][$key]];
                    } else {
                        $distance+= $cache[$clusters[$i][0][$key]– $p1];
                    }
                }
                $ii++;
                if ($distance < $smallest_distance) {
                    $smallest_distance = $distance;
                    $index = $i;
                }
            }
            $point_list[$index][] = $value;
        }
        $diff = 0;
        // 1个1个迭代k值
        $i = $k;
        while ($i–) {
            $old = $clusters[$i];
            // 移到到队列中心
            $center = calculateCenter($point_list[$i], 3);
            // 形成新的k值集合队列
            $new_cluster = array(
                $center,
                $point_list[$i]
            );
            $clusters[$i] = $new_cluster;
            // 计算新的k值与队列所在点的位置
            $diff = euclidean($old[0], $center);
        }
        // 判断是否已足够聚合
        if ($diff < $min_diff) {
            break; >
        }
    }
    echo '&mdash;>' . $ii;
    return $clusters;
}
// 计算2点距离
$ii = 0;
function euclidean($p1, $p2) {
    $s = 0;
    foreach ($p1 as $key => $value) {
        $temp = ($value– $p2[$key]);
        $s+= $temp * $temp;
    }
    return sqrt($s);
}
// 移动k值到所有点的中心
function calculateCenter($point_list, $attr_num) {
    $vals = array();
    $point_num = 0;
    $keys = array_keys($point_list[0]);
    foreach ($keys as $value) {
        $vals[$value] = 0;
    }
    foreach ($point_list as $arr) {
        $point_num++;
        foreach ($arr as $key => $value) {
            $vals[$key]+= $value;
        }
    }
    foreach ($keys as $index) {
        $vals[$index] = $vals[$index] / $point_num;
    }
    return $vals;
}
function RGBToHex($r, $g = ", $b=") {
    if (is_array($r)) {
        $b = $r['b'];
        $g = $r['g'];
        $r = $r['r'];
    }
    $hex = "#";
    $hex.= str_pad(dechex($r) , 2, '0', STR_PAD_LEFT);
    $hex.= str_pad(dechex($g) , 2, '0', STR_PAD_LEFT);
    $hex.= str_pad(dechex($b) , 2, '0', STR_PAD_LEFT);
    return $hex;
}
?>


本文地址:http://www.phprm.com/tuxiang/fs4848.html

转载随意,但请附上文章地址:-)

标签:k-means聚类算法 k-means主色调

仅有一条评论

  1. rainyluo rainyluo

    牛逼啊膜拜一下php版的聚类
    http://jnbaike.com

发表留言