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

39 投票
6 回答
63276 浏览
提问于 2025-04-16 02:50

我想要一些关于在Python中进行简单图像分析的建议。我需要计算一张图片的“亮度”值。我知道PIL是处理这类事情的首选库。它里面有一个内置的直方图功能。

我需要的是“感知亮度”的值,这样我才能判断是否需要对图片进行进一步调整。那么在这种情况下,有哪些基本的技术可以使用呢?我应该只处理RGB值,还是说直方图能给我提供足够接近的结果呢?

一个可能的解决方案是将这两者结合起来,先用直方图生成平均的红、绿、蓝值,然后再应用“感知亮度”的公式。

6 个回答

2

我觉得你可以先把RGB颜色转换成灰度,这样得到的结果会比较好。然后再对这个结果做直方图分析。至于用直方图计算平均值还是中位数哪个更合适,我不太确定,不过在大多数图像中,它们的结果可能差不多。

我不太清楚在PIL这个库里,怎么用任意公式把颜色转换成灰度,不过我猜应该是可以做到的。

3

如果你只是想要整张图片的平均值,而不是每个像素的亮度值,那么使用PIL库的直方图来计算平均值,再把这个结果应用到亮度函数上,似乎是最合适的方法。

如果你使用的是ImageMagick(配合PythonMagick),我建议你使用identify命令,并把“verbose”选项打开。这样你就能得到每个通道的平均值,这样就不用自己去计算直方图的总和和平均值了——你可以直接把每个通道的值相乘。

84

根据问题中提到的技术,我想出了几种不同的版本。

每种方法返回的值都很接近,但并不完全相同。而且,除了最后一种方法外,其他方法的运行速度差不多,最后一种方法的速度会因为图像大小而变得很慢。

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

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

    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. 计算像素的均方根值,然后转换为“感知亮度”。

    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]
    

更新测试结果 我对200张图像进行了模拟测试。发现方法#2和#4的结果几乎完全相同。而方法#3和#5的结果也非常接近。方法#1的结果紧随#3和#5之后(有一些例外情况)。

撰写回答