繁体   English   中英

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

[英]What are some methods to analyze image brightness using Python?

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

我需要的是一个“感知亮度”值,我可以决定是否需要对图像进行进一步调整。 那么在这种情况下可以使用哪些基本技术呢? 我应该只使用 RGB 值,还是直方图能给我足够接近的东西?

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

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

每个方法都返回一个 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]

更新测试结果我对 200 张图像进行了模拟。 我发现方法#2、#4 给出了几乎相同的结果。 此外,方法#3、#5 也几乎相同。 方法#1 紧随#3、#5(有几个例外)。

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

如果使用ImageMagick (使用PythonMagick绑定),我建议使用带有“verbose”选项集的识别命令。 这将为您提供每个通道的平均值,使您无需对直方图求和和求平均值——您可以直接将每个通道相乘。

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

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

下面的代码将为您提供 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())))

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

Scalar intensity = img.at<uchar>(y, x);
def calculate_brightness(image):

    greyscale_image = image.convert('L')
    histogram = greyscale_image.histogram()
    pixels = sum(histogram)
    brightness = scale = len(histogram)

    for index in range(0, scale):

        ratio = histogram[index] / pixels
        brightness += ratio * (-scale + index)
    return 1 if brightness == 255 else brightness / scale

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM