Как определить цвет фотографии?

Talker

Новичок
Как определить цвет фотографии?

Как определить средствами PHP какая фотография - черно-белая или цветная?
 

kruglov

Новичок
Встроенных средств типа is_picture_grayscale нету.
А свои мысли есть какие-нибудь?

-~{}~ 29.01.08 20:08:

p.s. [m]imagecopymergegray[/m]
 

Talker

Новичок
т.е. сравнить данные imagecopymergegray с imagecopymerge? хм, надо попробовать, спасибо за идею.
 

Фанат

oncle terrible
Команда форума
ну, врядли прямое сравнение поможет.
наверное, все-таки, imagecolorat

или ещё можно посмотреть в сторону imagemagick. там столько возможностей, что наверняка есть и это

kruglov, Давид написал "монохромные/цветные (ну, это просто)", а как - не написал =)
 

kruglov

Новичок
Ну, попиксельно - долго как-то... Хочется типа сделать нецветной, инвертировать, наложить на оригинал как-нить хитро, уменьшить результат до 1x1 и уж тогда применить imagecolorat.
 

kruglov

Новичок
А что, в жпеге внутри всегда написано, цветной он или нет?
Вот я сделал файлик, нарисовал черным на белом и сохранил в JPG. И все программы мне говорят, что цвет у него он 24-битный.
 

kruglov

Новичок
Фанат
У жпега палитры нету, там формулы придумываются для описания переливов цвета, чем в формулах коэффициентов больше, тем качество лучше.
 

Pigmeich

Новичок
Talker
Если фотки делаете вы - никаких проблем, даже в графику не лезьте.

Если не вы - не определите. Фотографы могут использовать перекосы по цветам для художественного воспроизведения ЧБ (для человека ЧБ, а на деле цвет). Могут использовать сепию, которая не как цвет воспринимается.
 

FractalizeR

Новичок
Определить на самом деле достаточно легко. У Grayscale картинок RGB значения находятся очень близко друг к другу.

PHP:
<?php
$imageColor = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/AutumnLeaves COLOR.jpg' );
$imageBW = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/AutumnLeaves BW.jpg' );

if (! $imageColor or ! $imageBW) {
	die ( 'Cannot load image!' );
}

echo (calculateColorSpaceValue ( $imageColor ));
echo ("\r\n");
echo (calculateColorSpaceValue ( $imageBW ));

function calculateColorSpaceValue($imageHandle) {
	$RGBVariance = 0;
	
	//Перебираем все пиксели
	for($x = 0; $x < imagesx ( $imageHandle ); $x ++) {
		for($y = 0; $y < imagesy ( $imageHandle ); $y ++) {
			
			//Получаем цвет очередного пикселя
			$color = imagecolorat ( $imageHandle, $x, $y );
			
			//Разбираем его на RGB
			$r = ($color >> 16) & 0xFF;
			$g = ($color >> 8) & 0xFF;
			$b = $color & 0xFF;
			
			//Рассчитываем сумму разниц между R, G и B значениями
			$RGBVariance += (abs ( $r - $g ) + abs ( $r - $b ) + abs ( $r - $b ));
		}
	}
	
	//Возвращаем коэффициент вариации
	return ($RGBVariance / (imagesx ( $imageHandle ) * imagesx ( $imageHandle )));
}
?>
Только что проверил работу этой своей функции на двух картинках из своей коллекции. Оригиналы - цветные копии. В черно-белые конвертил с помощью Paint.NET.

У обоих чернобелых моя calculateRGBVariance выдает 0. У всех цветных что-то близкое к 128.

Обратите внимание, что речь идет о grayscale, а не о сепии.

Перебор конечно тупой и грубый, но мне требовалось только привести пример. Функцию можно оптимизировать.

Картинки, на которых тестировал:

Осенние листья:
http://ipicture.ru/uploads/080130/R96g4SwmC0.jpg
http://ipicture.ru/uploads/080130/SAsTMKI93C.jpg

Пустыня:
http://ipicture.ru/uploads/080130/Qxncm8y0LR.jpg
http://ipicture.ru/uploads/080130/qD54cK9x8b.jpg
 

FractalizeR

Новичок
Спасибо за комплимент.
Включил сепию в эксперимент:

PHP:
<?php
$imageAutomnColor = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/AutumnLeaves COLOR.jpg' );
$imageAutomnBW = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/AutumnLeaves BW.jpg' );
$imageAutomnSepia = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/AutumnLeaves Sepia.jpg' );

$imageDesertColor = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/Desert Landscape COLOR.jpg' );
$imageDesertBW = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/Desert Landscape BW.jpg' );
$imageDesertSepia = imagecreatefromjpeg ( dirname ( __FILE__ ) . '/Desert Landscape Sepia.jpg' );

if (! $imageAutomnColor or ! $imageAutomnBW or ! $imageAutomnSepia or ! 
	$imageDesertColor or ! $imageDesertBW or ! $imageDesertSepia) {
		die ( 'Cannot load image!' );
}

echo ('Automn colored value: ' . calculateColorSpaceValue ( $imageAutomnColor ));
echo ("\r\n");
echo ('Automn BW value: ' . calculateColorSpaceValue ( $imageAutomnBW ));
echo ("\r\n");
echo ('Automn Sepia value: ' . calculateColorSpaceValue ( $imageAutomnSepia ));
echo ("\r\n");
echo ("\r\n");
echo ('Desert colored value: ' . calculateColorSpaceValue ( $imageDesertColor ));
echo ("\r\n");
echo ('Desert BW value: ' . calculateColorSpaceValue ( $imageDesertBW ));
echo ("\r\n");
echo ('Desert Sepia value: ' . calculateColorSpaceValue ( $imageDesertSepia ));

function calculateColorSpaceValue($imageHandle) {
	$RGBVariance = 0;
	
	//Перебираем все пиксели
	for($x = 0; $x < imagesx ( $imageHandle ); $x ++) {
		for($y = 0; $y < imagesy ( $imageHandle ); $y ++) {
			
			//Получаем цвет очередного пикселя
			$color = imagecolorat ( $imageHandle, $x, $y );
			
			//Разбираем его на RGB
			$r = ($color >> 16) & 0xFF;
			$g = ($color >> 8) & 0xFF;
			$b = $color & 0xFF;
			
			//Рассчитываем сумму разниц между R, G и B значениями
			$RGBVariance += (abs ( $r - $g ) + abs ( $r - $b ) + abs ( $r - $b ));
		}
	}
	
	//Возвращаем коэффициент вариации
	return ($RGBVariance / (imagesx ( $imageHandle ) * imagesx ( $imageHandle )));
}
?>
Результаты следующие:

Automn colored value: 122.3694562912
Automn BW value: 0
Automn Sepia value: 53.895827293396

Desert colored value: 127.08389949799
Desert BW value: 0
Desert Sepia value: 60.130362510681

-~{}~ 30.01.08 01:03:

P.S.
Спасибо автору за вопрос. Было интересно искать решение.
 

fixxxer

К.О.
Партнер клуба
оптимизация номер один - вынести imagesx ( $imageHandle ) из цикла =)
 

SiMM

Новичок
Ошибочка вышла :)
PHP:
$RGBVariance += (abs ( $r - $g ) + abs ( $r - $b ) + abs ( $r - $b ));
то же самое, что
PHP:
$RGBVariance += (abs ( $r - $g ) + 2*abs ( $r - $b ));
Как вариант
PHP:
function calculateColorSpaceValue($imageHandle) { 

  imagetruecolortopalette($imageHandle,false,256);
  $RGBVariance = 0;
  for ($i = imagecolorstotal($imageHandle); $i--;) {
    extract(imagecolorsforindex($imageHandle,$i));
    $RGBVariance += (abs ( $red - $green ) + abs ( $red - $blue ) + abs ( $green - $blue )); 
  }
  return $RGBVariance / imagecolorstotal($imageHandle);
}
но чистого нуля уже нет.
 

FractalizeR

Новичок
Да, прошу прощения, опечатался.

У меня все равно на моих картинках ноль получается на BW. Хотя я его и не ожидал. JPEG ведь с потерей качества сжимает.

оптимизация номер один - вынести imagesx ( $imageHandle ) из цикла =)
Совершенно верно. А еще неплохо бы применить как минимум чересстрочное сканирование. Незачем каждый пиксель изучать :)
 

kruglov

Новичок
JPEG ведь с потерей качества сжимает
Но не с потерей отсутствия цвета.

А еще неплохо бы применить как минимум чересстрочное сканирование
Ну мало ли, какой файл попадется клетчатый. Тогда уж лучше случайно выбирать.

-~{}~ 30.01.08 12:33:

Перебор конечно тупой и грубый, но мне требовалось только привести пример. Функцию можно оптимизировать.
Это очевидно, что можно попиксельно сравнить. Интересно было бы, чтобы попиксельность осталась на долю C++, а не PHP.
 

FractalizeR

Новичок
Ну так можно расширение написать для PHP, которое к GD будет обращаться самостоятельно. Только, думаю, это не то, что требовалось автору топика. Кстати, автор куда-то потерялся. Ни ответа ни привета....
 
Сверху