Обнаруживать, если изображение полутоновое или цветное, используя Imagick

Я пытаюсь попытаться присвоить значение изображению на основе его «уровня насыщенности», чтобы увидеть, является ли изображение черно-белым или цветным. Я использую Imagick и нашел то, что кажется идеальным кодом для командной строки, и пытаюсь реплицировать его с помощью библиотеки PHP.

Я думаю, что понимаю концепцию:

  1. Преобразование изображения в HSL.
  2. Извлеките канал «g» (который является S-каналом в HSL).
  3. Вычислите среднее значение этого канала.

Код командной строки

convert '$image_path' -colorspace HSL -channel g -separate +channel -format '%[fx:mean]' info: 

Мой PHP-код

 $imagick = new Imagick($image_path); $imagick->setColorspace(imagick::COLORSPACE_HSL); print_r($imagick->getImageChannelMean(imagick::CHANNEL_GREEN)); 

Вывод

Однако мой PHP-код не выводит одинаковые значения, такие как код командной строки. Например, изображение в оттенках серого дает 0 для кода командной строки, но код PHP дает [mean] => 10845.392051182 [standardDeviation] => 7367.5888849872 .

Аналогично, другое полутоновое изображение дает 0 против [mean] => 31380.528443457 [standardDeviation] => 19703.501101904 .

0.565309 изображение дает 0.565309 против [mean] => 33991.552881892 [standardDeviation] => 16254.018540044 .

Кажется, что между разными значениями не существует какой-либо картины. Я делаю что-то явно неправильно?

Благодарю.


Просто чтобы добавить, я также пробовал этот код PHP

 $imagick = new Imagick($image_path); $imagick->setColorspace(imagick::COLORSPACE_HSL); $imagick->separateImageChannel(imagick::CHANNEL_GREEN); $imagick->setFormat('%[fx:mean]'); 

Но я получаю сообщение Unable to set format ошибке « Unable to set format при попытке установить формат. Я также попробовал setFormat('%[fx:mean] info:') , setFormat('%[mean]') , setFormat('%mean') и т. Д.


Обновление – исправлено!

Благодаря @danack для выяснения, мне нужно было использовать transformImageColorspace() а не setColorspace() . Рабочий код приведен ниже.

 $imagick = new Imagick($image_path); $imagick->transformImageColorspace(imagick::COLORSPACE_HSL); $saturation_channel = $imagick->getImageChannelMean(imagick::CHANNEL_GREEN); $saturation_level = $saturation_channel['mean']/65535; 

    setFormat не реплицирует параметр командной строки -format – тот, который в Imagick пытается установить формат изображения, который должен быть png, jpg и т. д. В командной строке задается формат для info – ближайшего соответствия, для которого в Imagick вызывает $imagick->identifyImage(true) и анализирует результаты этого.

    Также вы просто вызываете неправильную функцию – это должно быть transformImageColorspace, а не setColorSpace. Если вы используете это, вы можете использовать статистику из getImageChannelMean.

    Существуют и другие способы проверки серости, которые могут быть более подходящими при определенных обстоятельствах. Первый – преобразовать клон изображения в оттенки серого, а затем сравнить его с исходным изображением:

     $imagick = new Imagick($image_path); $imagickGrey = clone $imagick; $imagickGrey->setimagetype(\Imagick::IMGTYPE_GRAYSCALE); $differenceInfo = $imagick->compareimages($imagickGrey, \Imagick::METRIC_MEANABSOLUTEERROR); if ($differenceInfo['mean'] <= 0.0000001) { echo "Grey enough"; } 

    Вероятно, это было бы уместно, если бы у вас были изображения с прозрачными областями, поэтому они теоретически имеют цвет, но не заметно.

    Или если вам все равно, будет ли изображение иметь формат в оттенках серого:

     $imageType = $imagick->getImageType(); if ($imageType === \Imagick::IMGTYPE_GRAYSCALE || $imageType === Imagick::IMGTYPE_GRAYSCALEMATTE) { //This is grayscale } 

    Я нашел здесь командную строку:

     convert image.png -colorspace HSL -channel g -separate +channel -format "%[fx:mean]" info: 

    Он печатает число от 0 до 1, где ноль означает оттенки серого.

    Если ваши изображения имеют оттенок. (например, от сканера), вы должны сделать автоматический цвет для них, прежде чем обнаруживать шкалу серого. Вы должны normalizeImage(imagick::CHANNEL_ALL) для всех отдельных каналов изображения. separateImageChannel()

    Но

    введите описание изображения здесь