Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Лекция



Привет, сегодня поговорим про определение доминирующих цветов на картинке на php методом k-средних, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое определение доминирующих цветов на картинке на php методом k-средних, методом страдних значений , настоятельно рекомендую прочитать все из категории Распознавание образов.

Определение доминирующих цветов на картинке. Реализация на PHP.

 

Медод k-means, он же метод k-средних, используется для распределения объектов на кластеры. В этой статье описывается сам алгоритм и то, как его можно применить для нахождения доминирующих цветов (цветов, которые встречаются чаще всего) на картинке.

 

 

 Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений
 
 
 
 

Немного теории

Те, кому не интересна суть метода, могут пролистать до части с кодом.

Кластер в нужном нам смысле — это группа объектов с близкими по значению свойствами. У объектов может быть одно свойство, а может быть и несколько. Кстати, эти свойства — числа. Задача состоит в том, чтобы разбить имеющиеся объекты на определенное количество кластеров так, чтобы сумма отклонений от центра кластеров была минимальна. В итоге получится нужное количество "кучек" объектов.

Для простоты рассмотрим пример с множество объектов с 2-мя свойствами. Эть свойства будем представлять как координаты x и y на плоскости. Пусть у нас будет заранее заданное множество точек.

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Далее из текущего числа объектов случайно определим как центроиды (обозначены звездами) столько точек, сколько надо выделить кластеров.

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Теперь начинается цикл. Сначала для каждого объекта определяем ближайший к нему центроид, тем самым распределяем объекты по группам.

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Далее для каждой группы объектов определяем центр масс и переносим туда центроид этой группы.

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Цикл повторяется до тех пор, пока суммарный сдвиг центроидов в одном цикле не окажется меньше заранее заданной величины. В итоге текущие центроды и окажутся кластерами.

Определение доминирующих цветов на картинке на PHP методом k-средних и методом страдних значений

Применение метода для определение доминирующих цветов

Здесь все очень просто :). В качестве объектов используются цвета пикселей, а свойства — значение красного, синего и зеленого канала цвета.

// Функция, которая определяет "расстояние" между объектами
function getDistance($arr1, $arr2, $l) {
	// Определяется "расстояние машины такси" — так быстрее, но для более точного результата желательно использовать евклидому метрику
	$s = 0;
	for($i = 0; $i < $l; ++$i)
		$s += $arr1[$i] > $arr2[$i] ? ($arr1[$i] - $arr2[$i]) : ($arr2[$i] - $arr1[$i]);
	return $s;
}

/*
Сама функция, которая определяет доминирующие цвета
Значения, передаваемые функции:
	$url — путь к картинке на сервере
	$amount — количество цветов, которые надо определить
	$sort — сортировать ли цвета по убыванию встречаемости на картинке
	$maxPreSize — максимальный размер уменьшаемой картинки (подробнее чуть дальше)
	$epselon — минимальное суммарное отклонение, необходимое для выхода из цикла
*/
function getDominantColors($url, $amount = 1, $sort = true, $maxPreSize = 50, $epselon = 1) {
	// Определяем, существует ли указанный файл. Об этом говорит сайт https://intellect.icu  . Если нет, то выдаем ошибку.
	if(!file_exists($url))
		return false;
	// Определяем размер картинки, если это картинка.
	$size = getimagesize($url);
	if($size === false)
		return false;
	$width = $size[0];
	$height = $size[1];
	// Определяем формат изображения из заголовка файла и проверяем, есть ли функция, которая может это изображение открыть. Если нет, значит файл — не картинка, и выдаем ошибку.
	$format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
	if($format == 'x-ms-bmp')
		$format = 'wbmp';
	$func = 'imagecreatefrom'.$format;
	if(!function_exists($func))
		return false;
	$bitmap = @$func($url);
	if(!$bitmap)
		return false;

	// Здесь мы уменьшаем исходную картинку, чтобы иметь дело не со всеми пикселями, а только с некоторыми. Это значительно увеличивает скорость алгоритма. Чем меньше размер — тем меньше точность.
	$newW = $width > $maxPreSize ? $maxPreSize : $width;
	$newH = $height > $maxPreSize ? $maxPreSize : $height;
	$bitmapNew = imagecreatetruecolor($newW, $newH);
	// Для большей точности надо использовать функцию imageCopyResambled, но она тратит очень много времени, поэтому используется быстрая и грубая функция imageCopyResized.
	imageCopyResized($bitmapNew, $bitmap, 0, 0, 0, 0, $newW, $newH, $width, $height);
	// Заносим цвета  всех пикселей в один массив
	$pixelsAmount = $newW * $newH;
	$pixels = Array();
	for($i = 0; $i < $newW; ++$i)
		for($j = 0; $j < $newH; ++$j) {
			$rgb = imagecolorat($bitmapNew, $i, $j);
			$pixels[] = Array(
				($rgb >> 16) & 0xFF,
				($rgb >> 8) & 0xFF,
				$rgb & 0xFF
			);
		}
	imagedestroy($bitmapNew);
	
	// Выбираем случайные пиксели для установки центроидов в них
	$clusters = Array();
	$pixelsChosen = Array();
	for($i = 0; $i < $amount; ++$i) {
		// Желательно не ставить несколько центроидов в одну точку
		do {
			$id = rand(0, $pixelsAmount - 1);
		} while(in_array($id, $pixelsChosen));
		$pixelsChosen[] = $id;
		$clusters[] = $pixels[$id];
	}
	
	$clustersPixels = Array();
	$clustersAmounts = Array();
	// Начинаем цикл
	do {
		// Обнуляем хранилище пикселей, принадлежащих текущему центроиду и их счетчик
		for($i = 0; $i < $amount; ++$i) {
			$clustersPixels[$i] = Array();
			$clustersAmounts[$i] = 0;
		}
		
		// Проходимся по всем пикселям и определяем ближайший к ним центроид	
		for($i = 0; $i < $pixelsAmount; ++$i) {
			$distMin = -1;
			$id = 0;
			for($j = 0; $j < $amount; ++$j) {
				$dist = getDistance($pixels[$i], $clusters[$j], 3);
				if($distMin == -1 or $dist < $distMin) {
					$distMin = $dist;
					$id = $j;
				}
			}
			$clustersPixels[$id][] = $i;
			++$clustersAmounts[$id];
		}
		
		// Перемещаем центроид в центр масс пикселей, принадлежащих ему, заодно вычисляем, насколько он сместился
		$diff = 0;
		for($i = 0; $i < $amount; ++$i) {
			if($clustersAmounts[$i] > 0) {
				$old = $clusters[$i];
				for($k = 0; $k < 3; ++$k) {
					$clusters[$i][$k] = 0;
					for($j = 0; $j < $clustersAmounts[$i]; ++$j)
						$clusters[$i][$k] += $pixels[$clustersPixels[$i][$j]][$k];
					$clusters[$i][$k] /= $clustersAmounts[$i];
				}
				// Будем сравнивать максимальное отклонение
				$dist = getDistance($old, $clusters[$i], 3);
				$diff = $diff > $dist ? $diff : $dist;
			}
		}
	} while($diff >= $epselon);
	
	// Сортировка получившихся кластеров (не помню как метод называется)
	if($sort and $amount > 1)
		for($i = 1; $i < $amount; ++$i)
			for($j = $i; $j >= 1 and $clustersAmounts[$j] > $clustersAmounts[$j - 1]; --$j) {
				$t = $clustersAmounts[$j - 1];
				$clustersAmounts[$j - 1] = $clustersAmounts[$j];
				$clustersAmounts[$j] = $t;
				
				$t = $clusters[$j - 1];
				$clusters[$j - 1] = $clusters[$j];
				$clusters[$j] = $t;
			}
	
	// Значение цвета — величина целая, поэтому ее надо округлить
	for($i = 0; $i < $amount; ++$i)
		for($j = 0; $j < 3; ++$j)
			$clusters[$i][$j] = floor($clusters[$i][$j]);
	
	// Очищаем память
	imagedestroy($bitmap);
	
	// Возвращаем массив, который содержит доминирующие цвета. Каждый цвет — массив, состоящий из 3-х элементов — красный, зеленый и синий канал цвета.
	return $clusters;
}

$colors = getDominantColors('my_picture.jpg', 3);
if($colors === false)
	echo 'Ошибка';
else
	foreach($colors as $color)
		echo '<div style="width: 50px; height: 40px; background-color: rgba($color[0], $color[1], $color[2], 1);"></div>';



второй способ

<?php
/**
* Class for Generator Image Color Palette.
* This file is class for return mamimum used colors in image, format return in HTML or RGB format.
*
* PHP versions 4 and 5
* Licensed under The GPL License
*
* Developed By Kalpeh Gamit
* E-mail Kalpa.programmer@gmail.com
*
* @filesource
* @copyright Copyright 2009, InScripter Inc. (http://www.inscripter.com)
* @link http://www.inscripter.com
* @package PHP
* @version GetImageColor-1.0.0
* @license http://www.opensource.org/licenses/gpl-2.0.php The GPL License
*/

// start of class : Generator Image Color Palette
class GeneratorImageColorPalette
{
// get image color in RGB format function
function getImageColor($imageFile_URL, $numColors, $image_granularity = 5)
{
$image_granularity = max(1, abs((int)$image_granularity));
$colors = array();
//find image size
$size = @getimagesize($imageFile_URL);
if($size === false)
{
user_error("Unable to get image size data");
return false;
}
// open image
$img = @imagecreatefromjpeg($imageFile_URL);
if(!$img)
{
user_error("Unable to open image file");
return false;
}

// fetch color in RGB format



$startx= round($size[0] / 4);
$endx= $size[0] -round($size[0] / 4);

$starty= round($size[1] / 4);
$endy= $size[1] -round($size[1] / 4);

for($x = $startx ; $x < $endx; $x += $image_granularity)
{
for($y =$starty; $y < $endy; $y += $image_granularity)
{
$thisColor = imagecolorat($img, $x, $y);
$rgb = imagecolorsforindex($img, $thisColor);
$red = round(round(($rgb['red'] / 0x33)) * 0x33);
$green = round(round(($rgb['green'] / 0x33)) * 0x33);
$blue = round(round(($rgb['blue'] / 0x33)) * 0x33);
$thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue);
if(array_key_exists($thisRGB, $colors))
{
$colors[$thisRGB]++;
}
else
{
$colors[$thisRGB] = 1;
}
}
}
arsort($colors);
// returns maximum used color of image format like #C0C0C0.
return array_slice( ($colors), 0, $numColors, true);
}

// html color to convert in RGB format color like R(255) G(255) B(255)
function getHtml2Rgb($str_color)
{
if ($str_color[0] == '#')
$str_color = substr($str_color, 1);

if (strlen($str_color) == 6)
list($r, $g, $b) = array($str_color[0].$str_color[1],
$str_color[2].$str_color[3],
$str_color[4].$str_color[5]);
elseif (strlen($str_color) == 3)
list($r, $g, $b) = array($str_color[0].$str_color[0], $str_color[1].$str_color[1], $str_color[2].$str_color[2]);
else
return false;

$r = hexdec($r); $g = hexdec($g); $b = hexdec($b);
$arr_rgb = array($r, $g, $b);
// Return colors format liek R(255) G(255) B(255)
return $arr_rgb;
}

// end of class here : Generator Image Color Palette
}
?>

 

 

<?php
require_once "getImageColor.php";// подключаем файл со скриптом
$img = new GeneratorImageColorPalette();
$colors = $img->getImageColor('1.jpg', 4, $image_granularity = 1);
print_r($colors);
foreach($colors as $color=>$cnt)

echo "<div style='background:#". ($color)."; width:100px; height:100px '></div><br />";
?>

результаты проверки цвета первым методом в самом начале статьи

вторым методом

Array ( [FFFFFF] => 4960 [CCCCCC] => 785 [FFFFCC] => 423 [FFCCFF] => 316 )
 
 
 

 

 

 

 
 





 

Надеюсь, эта статья про определение доминирующих цветов на картинке на php методом k-средних, была вам полезна, счастья и удачи в ваших начинаниях! Надеюсь, что теперь ты понял что такое определение доминирующих цветов на картинке на php методом k-средних, методом страдних значений и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Распознавание образов

создано: 2015-03-23
обновлено: 2024-11-14
410



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Распознавание образов

Термины: Распознавание образов