使用Python分析图像亮度有哪些方法?

时间:2010-08-16 05:09:43

标签: python image-processing

我想在python中执行简单的图像分析。我需要计算图像“亮度”的值。我知道PIL是用于执行此类操作的goto库。有一个内置的直方图功能。

我需要的是"perceived brightness"值我可以决定是否需要进一步调整图像。那么在这种情况下哪些基本技术会起作用呢?我应该只使用RGB值,还是直方图能给我一些足够接近的东西?

一种可能的解决方案可能是将两者结合起来,并使用直方图生成平均R,G和B值,然后应用“感知亮度”公式。

5 个答案:

答案 0 :(得分:43)

使用问题中提到的技术,我提出了几个不同的版本。

每个方法返回一个值close,但与其他方法不完全相同。此外,除最后一个方法外,所有方法都以大致相同的速度运行,根据图像大小,速度要慢得多。

  1. 将图像转换为灰度,返回平均像素亮度。

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.mean[0]
    
  2. 将图像转换为灰度,返回RMS像素亮度。

    def brightness( im_file ):
       im = Image.open(im_file).convert('L')
       stat = ImageStat.Stat(im)
       return stat.rms[0]
    
  3. 平均像素,然后转换为“感知亮度”。

    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))
    
  4. 像素的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))
    
  5. 计算像素的“感知亮度”,然后返回平均值。

    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]
    
  6. 更新测试结果 我针对200张图片进行了模拟。我发现方法#2,#4给出了几乎相同的结果。方法#3,#5也几乎相同。方法#1紧跟#3,#5(除了少数例外)。

答案 1 :(得分:2)

鉴于您只是在寻找整个图像的平均值,而不是每像素亮度值,平均PIL的直方图并将亮度函数应用于输出似乎是该库的最佳方法。

如果使用ImageMagick(带PythonMagick绑定),我建议使用identify命令并设置“verbose”选项。这将为您提供每个通道的平均值,从而节省您对直方图求和和平均值的需要 - 您可以直接乘以每个通道。

答案 2 :(得分:1)

我认为您最好的结果将来自使用您喜欢的公式将RGB转换为灰度,然后获取该结果的直方图。我不确定直方图的均值或中位数是否更合适,但在大多数图像上它们可能相似。

我不确定如何使用任意公式在PIL中转换为灰度,但我猜它是可能的。

答案 3 :(得分:1)

下面的代码将为您提供0-10之间的图像亮度级别

1使用opencv将图像转换为HSV格式后,计算图像的平均亮度。

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())))

答案 4 :(得分:0)

这可以通过将 BGR 图像从 cv2 转换为灰度,然后找到强度来完成 - x 和 y 是像素坐标。此 https://docs.opencv.org/3.4/d5/d98/tutorial_mat_operations.html 文档对此进行了很好的解释。

Scalar intensity = img.at<uchar>(y, x);