Быстро получить яркость / яркость изображений

Я работаю в php, и прохождение каждого изображения попиксельно, чтобы получить среднюю яркость для каждого изображения, будет очень интенсивным процессором...

Я просматривал документы GD и imagemagick, но не нашел способа вернуть среднюю яркость изображения... Это можно сделать быстро либо в этих библиотеках, либо в другом пакете, легко доступном для php?

4 ответа

Решение

Вот интересный пост, использующий ImageMagick для вычисления среднего уровня изображения. В этом посте также обсуждается методика уменьшения размера Марка Рэнсома до 1x1 с помощью ImageMagick.

В командной строке Imagemagick вы можете преобразовать в HSI или LAB и получить яркость (интенсивность или яркость) из среднего значения I или L канала. Любой из этих методов должен работать. Обратите внимание, что -scale 1x1 делает простое среднее для всего изображения / канала и сохраняет это значение в 1 пиксельном результате. Масштаб очень быстро. Это не похоже на -resize, который использует особую функцию фильтра. Кроме того, вы можете просто вычислить среднее значение изображения без записи в 1 пиксель.

convert image -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]\n" info:

convert image -colorspace LAB -channel r -separate +channel -scale 1x1 -format "%[fx:100*u]\n" info:

convert image -colorspace HSI -channel b -separate +channel -format "%[fx:100*u.mean]\n" info:

convert image -colorspace LAB -channel r -separate +channel -format "%[fx:100*u.mean]\n" info:

convert image -colorspace HSI -channel b -separate +channel -format "%[mean]\n" info:

convert image -colorspace LAB -channel r -separate +channel -format "%[mean]\n" info:


Результат будет между 0 и 100%, где 0 будет черным, а 100 - белым для всех, кроме двух последних, где диапазон fx находится в диапазоне от 0 до 1. Таким образом, коэффициент 100 для получения процента. Для двух последних команд значения будут в диапазоне от 0 до 255 для установки Q8 и от 0 до 65535 для установки Q16.

Обратите внимание, что каналы помечены по порядку, как если бы они были r, g, b. Но для современных версий Imagemagick вы можете использовать 0,1,2.

Кроме того, вы можете получить цвет пикселя для канала, который будет иметь некоторое значение серого:

convert image -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[pixel:u.p{0,0}]\n" info:

convert image -colorspace LAB -channel r -separate +channel -scale 1x1 -format "%[pixel:u.p{0,0}]\n" info:


Извини, я не знаю Имагик, но вижу

http://us3.php.net/manual/en/imagick.scaleimage.php

http://us3.php.net/manual/en/imagick.getimagepixelcolor.php

http://us3.php.net/manual/en/imagick.transformimagecolorspace.php

http://us3.php.net/manual/en/imagick.getimagechannelstatistics.php

или возможно

http://us3.php.net/manual/en/imagick.getimageproperty.php

Возможно, эксперт Imagick будет достаточно любезен, чтобы преобразовать одну из этих команд из командной строки в код Imagick.

Образец? Просто выберите 10% случайных пикселей вместо 100%... Частота ошибок, очевидно, возрастет, но 10% пикселей мне кажутся хорошими, в большинстве случаев это должно дать отличные результаты!

Кэшируйте значения, если используете их более одного раза, потому что это не быстрое решение. Сначала я попытался изменить размер изображения до 1x1 пикселя с помощью imagick, но результаты оказались не очень хорошими. Лучшие результаты, которые я получил без изменения размера imagick, но это очень медленно с большими изображениями. Пример изменяет размер до 1000x1000 пикселей. Имейте в виду, что этот пример не охватывает изображения с альфа-каналом.

function getImageBrightness( $path )
{
    $width  = 1000;
    $height = 1000;

    try
    {
        $imagick = new imagick( $path );
        $imagick->resizeImage( $width, $height );

        $_brightness = 0;

        for( $i=0; $i < $width; $i++ )
            for( $j=0; $j < $height; $j++ )
                if( $pixel = $imagick->getImagePixelColor($i, $j) )
                    if( $colors = $pixel->getColor() AND isset($colors['r']) )
                    {
                        $brightness = ($colors['r'] + $colors['g'] + $colors['b']) / (3* 255);

                        $_brightness = $brightness + $_brightness;
                    }

        $_brightness = $_brightness / ( $height * $width );

        return $_brightness; // from 0 (black) to 1 (white)

    } catch( ImagickException $e )
    {}

    return 0.5;  // default
}

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

Производительность будет зависеть от количества цветов в изображении / гистограмме (например, одноцветное изображение будет очень быстрым).

<?php

$image = new Imagick('image.jpg');
$pixels = $image->getImageHistogram();  // Generate histogram of colors

$sumbright = 0;  // sum of brightness values
$cntbright = 0;  // count of pixels

foreach($pixels as $p){
  $color = $p->getColor();  // Get rbg pixel color
  $cnt = $p->getColorCount();  // Get number of pixels with above color

  $sumbright += (($color['r'] + $color['g'] + $color['b']) / (3*255)) * $cnt;  // Calculate 0.0 - 1.0 value of brightness (0=rgb[0] 1=rgb[255])

  $cntbright += $cnt;
}

$avgbright = $sumbright / $cntbright;  // Average 0-1 brightness of all pixels in the histogram

?>
Другие вопросы по тегам