Каковы некоторые методы анализа яркости изображения с помощью Python?

Мне бы хотелось получить совет по выполнению простого анализа изображений в python. Мне нужно вычислить значение для "яркости" изображения. Я знаю PIL - это библиотека goto для выполнения чего-то подобного. Существует встроенная функция гистограммы.

Что мне нужно - это "воспринимаемая яркость" . Я могу решить, необходимы ли дополнительные корректировки изображения. Итак, что же из основных техник, которые будут работать в этой ситуации? Должен ли я просто работать с значениями RGB, или гистограмма даст мне что-то достаточно близко?

Одним из возможных решений может быть объединение этих двух и получение средних значений R, G и B с использованием гистограммы, затем применение формулы "воспринимаемой яркости".

Ответы

Ответ 1

Используя методы, упомянутые в вопросе, я придумал несколько разных версий.

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

  • Преобразовать изображение в оттенки серого, вернуть среднюю яркость пикселей.

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.mean[0]
    
  • Преобразовать изображение в оттенки серого, вернуть яркость пикселей RMS.

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.rms[0]
    
  • Средние пиксели, затем преобразуются в "воспринимаемую яркость" .

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       r,g,b = stat.mean
       return math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2))
    
  • RMS пикселей, затем преобразуется в "воспринимаемую яркость" .

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       r,g,b = stat.rms
       return math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2))
    
  • Рассчитайте "воспринимаемую яркость" пикселей, затем верните средний результат.

    def brightness( im_file ):
       im = Image.open(im_file)
       stat = ImageStat.Stat(im)
       gs = (math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2)) 
             for r,g,b in im.getdata())
       return sum(gs)/stat.count[0]
    

Обновить результаты тестирования Я провел симуляцию против 200 изображений. Я обнаружил, что методы № 2, №4 дали почти одинаковые результаты. Также методы № 3, № 5 были также почти идентичны. Метод № 1 внимательно следил за # 3, # 5 (за некоторыми исключениями).

Ответ 2

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

Если вы используете ImageMagickPythonMagick bindings), я бы предложил использовать команду identify с установленной опцией "verbose". Это обеспечит вам среднее значение для каждого канала, что позволит вам суммировать и усреднить гистограмму; вы можете просто размножать каждый канал напрямую.

Ответ 3

Я думаю, что ваш лучший результат будет заключаться в преобразовании RGB в оттенки серого с использованием вашей любимой формулы, а затем с гистограммой этого результата. Я не уверен, будет ли среднее или медианное значение гистограммы более подходящим, но на большинстве изображений они, вероятно, похожи.

Я не уверен, как сделать преобразование в оттенки серого в PIL, используя произвольную формулу, но я предполагаю, что это возможно.

Ответ 4

Эй, у меня есть точная проблема.. Я надеюсь, что эта ссылка https://github.com/imneonizer/How-to-find-if-an-image-is-bright-or-dark/blob/master/README.md будет помочь вам достичь того же. В этом блоге я объяснил, как я разделил изображение на более мелкие сегменты и нашел яркость в этих сегментах и, наконец, взял среднее значение всех этих рассчитанных яркостей, чтобы получить уровень яркости изображения. Он может легко определить, какие изображения являются более яркими, а какие - темными. Надеюсь, это может вам чем-то помочь.

Ответ 5

код ниже даст вам уровень яркости изображения от 0 до 10

1 вычислите среднюю яркость изображения после преобразования изображения в формат HSV с помощью opencv.

2 найти, где это значение лежит в списке диапазона яркости.

 import numpy as np
 import cv2
 import sys
 from collections import namedtuple

#brange brightness range
#bval brightness value
BLevel = namedtuple("BLevel", ['brange', 'bval'])

#all possible levels
_blevels = [
    BLevel(brange=range(0, 24), bval=0),
    BLevel(brange=range(23, 47), bval=1),
    BLevel(brange=range(46, 70), bval=2),
    BLevel(brange=range(69, 93), bval=3),
    BLevel(brange=range(92, 116), bval=4),
    BLevel(brange=range(115, 140), bval=5),
    BLevel(brange=range(139, 163), bval=6),
    BLevel(brange=range(162, 186), bval=7),
    BLevel(brange=range(185, 209), bval=8),
    BLevel(brange=range(208, 232), bval=9),
    BLevel(brange=range(231, 256), bval=10),
]


def detect_level(h_val):
     h_val = int(h_val)
     for blevel in _blevels:
        if h_val in blevel.brange:
            return blevel.bval
    raise ValueError("Brightness Level Out of Range")


 def get_img_avg_brightness():
     if len(sys.argv) < 2:
        print("USAGE: python3.7 brightness.py <image_path>")
        sys.exit(1)
     img = cv2.imread(sys.argv[1])
     hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
     _, _, v = cv2.split(hsv)

     return int(np.average(v.flatten()))

 if __name__ == '__main__':

     print("the image brightness level is: 
            {0}".format(detect_level(get_img_avg_brightness())))