首页 > 语言 > PHP > 正文

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

2024-09-04 11:44:30
字体:
来源:转载
供稿:网友

 

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

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

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

  1. <?php  
  2.  
  3. $start = microtime(TRUE);  
  4.  
  5. main(); 
  6.  
  7. function main($img = ‘colors_files/T1OX3eXldXXXcqfYM._111424.jpg’)  
  8.  
  9. {  
  10.     
  11. list($width$height$mime_code) = getimagesize($img);  
  12. //开源代码Vevb.com 
  13.  
  14.  
  15. $im = null;  
  16.  
  17. $point = array();  
  18.  
  19. switch ($mime_code)  
  20.  
  21. {  
  22.  
  23. # jpg  
  24.  
  25. case 2:  
  26.  
  27. $im =imagecreatefromjpeg($img);  
  28.  
  29. break;  
  30.  
  31.  
  32.  
  33. # png  
  34.  
  35. case 3:  
  36.   
  37. default:  
  38.  
  39. exit(‘擦 ,什么图像?解析不了啊’);  
  40.  
  41. }  
  42.   
  43. $new_width = 100;  
  44.  
  45. $new_height = 100;  
  46.  
  47. $pixel = imagecreatetruecolor($new_width$new_height);  
  48.  
  49. imagecopyresampled($pixel$im, 0, 0, 0, 0, $new_width$new_height$width$height);  
  50.   
  51. run_time();  
  52.   
  53. $i = $new_width;  
  54.  
  55. while ($i–)  
  56.  
  57. {  
  58.  
  59. # reset高度  
  60.  
  61. $k = $new_height;  
  62.  
  63. while ($k–)  
  64.  
  65. {  
  66.  
  67. $rgb = ImageColorAt($im$i$k);  
  68.  
  69. array_push($pointarray(‘r’=>($rgb >> 16) & 0xFF, ‘g’=>($rgb >> 8) & 0xFF, ‘b’=>$rgb & 0xFF));  
  70.  
  71. }  
  72.  
  73. }  
  74.  
  75. imagedestroy($im);  
  76.  
  77. imagedestroy($pixel); 
  78.  
  79. run_time();  
  80.   
  81. $color = kmeans($point);  
  82.   
  83. run_time();
  84.   
  85. foreach ($color as $key => $value)  
  86.  
  87. &nb 
  88. sp; {  
  89.  
  90. echo ‘<br><span style=“background-color:’ . RGBToHex($value[0]) . ‘” >’ . RGBToHex($value[0]) . ‘</span>’;  
  91.  
  92. }  
  93.   
  94. }  
  95.   
  96. function run_time()  
  97.  
  98. {  
  99.  
  100. global $start;  
  101.  
  102. echo ‘<br/>消耗:’, microtime(TRUE) – $start;  
  103.  
  104. }  
  105.   
  106. function kmeans($point=array(), $k=3, $min_diff=1)  
  107.  
  108. {  
  109.  
  110. global $ii;  
  111.  
  112. $point_len = count($point);  
  113.  
  114. $clusters = array();  
  115.  
  116. $cache = array();  
  117.     
  118. for ($i=0; $i < 256; $i++)  
  119.  
  120. {  
  121.  
  122. $cache[$i] = $i*$i;  
  123.  
  124. } 
  125.  
  126. # 随机生成k值  
  127.  
  128. $i = $k;  
  129.  
  130. $index = 0;  
  131.  
  132. while ($i–)  
  133.  
  134. {  
  135.  
  136. $index = mt_rand(1,$point_len-100);  
  137.  
  138. array_push($clustersarray($point[$index], array($point[$index])));  
  139.  
  140. }  
  141.  
  142. run_time();  
  143.  
  144. $point_list = array();  
  145.   
  146. $run_num = 0;  
  147.   
  148. while (TRUE)  
  149.  
  150. {  
  151.  
  152. foreach ($point as $value)  
  153.  
  154. {  
  155.  
  156. $smallest_distance = 10000000;  
  157.   
  158. # 求出距离最小的点  
  159.  
  160. # index用于保存point最靠近的k值  
  161.  
  162. $index = 0;  
  163.  
  164. $i = $k;  
  165.  
  166. while ($i–)  
  167.  
  168. {  
  169.  
  170. $distance = 0;  
  171.  
  172. foreach ($value as $key => $p1)  
  173.  
  174. {  
  175.  
  176. &n 
  177. bsp; if ($p1 > $clusters[$i][0][$key])  
  178.  
  179. {  
  180.  
  181. $distance += $cache[$p1 - $clusters[$i][0][$key]];  
  182.  
  183. }  
  184.  
  185. else  
  186.  
  187. {  
  188.  
  189. $distance += $cache[$clusters[$i][0][$key] – $p1];  
  190.  
  191. }  
  192.  
  193. } 
  194.  
  195. $ii++;  
  196.  
  197.  
  198. if ($distance < $smallest_distance)  
  199.  
  200. {  
  201.  
  202. $smallest_distance = $distance;  
  203.  
  204. $index = $i;  
  205.  
  206. }  
  207.  
  208. }  
  209.  
  210. $point_list[$index][] = $value;  
  211.  
  212. }  
  213.   
  214. $diff = 0;  
  215.  
  216. # 1个1个迭代k值  
  217.  
  218. $i = $k;  
  219.  
  220. while ($i–)  
  221.  
  222. {  
  223.  
  224. $old = $clusters[$i];  
  225.   
  226. # 移到到队列中心  
  227.  
  228. $center = calculateCenter($point_list[$i], 3);  
  229.  
  230. # 形成新的k值集合队列  
  231.  
  232. $new_cluster = array($center$point_list[$i]);  
  233.  
  234. $clusters[$i] = $new_cluster;  
  235.   
  236. # 计算新的k值与队列所在点的位置  
  237.  
  238. $diff = euclidean($old[0], $center);  
  239.  
  240. } 
  241.  
  242. # 判断是否已足够聚合  
  243.  
  244. if ($diff < $min_diff)  
  245.  
  246. {  
  247.  
  248. break;  
  249.  
  250. }  
  251. }  
  252.  
  253. echo ‘—>’.$ii;  
  254.   
  255. return $clusters;  
  256.  
  257. }  
  258.   
  259. # 计算2点距离  
  260.  
  261. $ii = 0;  
  262.  
  263. function euclidean($p1$p2)  
  264.  
  265. {  
  266.   
  267. $s = 0;  
  268.  
  269. foreach ($p1 as $key => $value)  
  270.  
  271. {  
  272.   
  273. $temp = ($value – $p2[$key]);  
  274.  
  275. $s += $temp*$temp;  
  276.  
  277. } 
  278.  
  279. return sqrt($s);  
  280. }  
  281.   
  282. # 移动k值到所有点的中心  
  283.  
  284. function calculateCenter($point_list$attr_num) {  
  285.  
  286. $vals = array();  
  287.  
  288. $point_num = 0;  
  289.  
  290.  
  291.  
  292. $keys = array_keys($point_list[0]);  
  293.  
  294. foreach($keys as $value)  
  295.  
  296. {  
  297.  
  298. $vals[$value] = 0;  
  299.  
  300. }  
  301. foreach ($point_list as $arr)  
  302.  
  303. {  
  304.  
  305. $point_num++;  
  306.  
  307. foreach ($arr as $key => $value)  
  308.  
  309. {  
  310.  
  311. $vals[$key] += $value;  
  312.  
  313. }  
  314.  
  315. }    
  316. foreach ($keys as $index)  
  317.  
  318. {  
  319.  
  320. $vals[$index] = $vals[$index] / $point_num;  
  321.  
  322. }  
  323.   
  324. return $vals;  
  325.  
  326. }     
  327.  
  328. function RGBToHex($r$g=”, $b=”)  
  329.  
  330. {  
  331.  
  332. if (is_array($r))  
  333.  
  334. {  
  335.  
  336. $b = $r['b'];  
  337.  
  338. $g = $r['g'];  
  339.  
  340.  
  341. $r = $r['r'];  
  342.  
  343. }  
  344.   
  345. $hex = “#”;  
  346.  
  347. $hex.= str_pad(dechex($r), 2, ’0′, STR_PAD_LEFT);  
  348.  
  349. $hex.= str_pad(dechex($g), 2, ’0′, STR_PAD_LEFT);  
  350.  
  351. $hex.= str_pad(dechex($b), 2, ’0′, STR_PAD_LEFT);  
  352.   
  353. return $hex;  
  354.  
  355. }  
  356.  
  357. ?>

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表