简体   繁体   English

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

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

I'd like some advice on performing a simple image analysis in python.我想要一些关于在 python 中执行简单图像分析的建议。 I need to calculate a value for the "brightness" of an image.我需要计算图像“亮度”的值。 I know PIL is the goto library for doing something like this.我知道PIL是执行此类操作的 goto 库。 There is a built-in histogram function.有一个内置的直方图功能。

What I need is a "perceived brightness" values I can decide if further adjustments to the image are necessary.我需要的是一个“感知亮度”值,我可以决定是否需要对图像进行进一步调整。 So what are something of the basic techniques that will work in this situation?那么在这种情况下可以使用哪些基本技术呢? Should I just work with the RGB values, or will histogram give me something close enough?我应该只使用 RGB 值,还是直方图能给我足够接近的东西?

One possible solution might be to combine the two, and generate average R,G,and B values using the histogram, then apply the "perceived brightness" formula.一种可能的解决方案可能是将两者结合起来,并使用直方图生成平均 R、G 和 B 值,然后应用“感知亮度”公式。

Using the techniques mentioned in the question, I came up with a few different versions.使用问题中提到的技术,我想出了几个不同的版本。

Each method returns a value close, but not exactly the same as the others.每个方法都返回一个 close 值,但与其他方法不完全相同。 Also, all methods run about the same speed except for the last one, which is much slower depending on the image size.此外,除最后一种方法外,所有方法的运行速度大致相同,后者根据图像大小慢得多。

  1. Convert image to greyscale, return average pixel brightness.将图像转换为灰度,返回平均像素亮度。

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

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

     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 of pixels, then transform to "perceived brightness".像素的 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. Calculate "perceived brightness" of pixels, then return average.计算像素的“感知亮度”,然后返回平均值。

     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]

Update Test Results I ran a simulation against 200 images.更新测试结果我对 200 张图像进行了模拟。 I found that methods #2, #4 gave almost identical results.我发现方法#2、#4 给出了几乎相同的结果。 Also methods #3, #5 were also nearly identical.此外,方法#3、#5 也几乎相同。 Method #1 closely followed #3, #5 (with a few exceptions).方法#1 紧随#3、#5(有几个例外)。

Given that you're just looking for an average across the whole image, and not per-pixel brightness values, averaging PIL's histogram and applying the brightness function to the output seems like the best approach for that library.鉴于您只是在寻找整个图像的平均值,而不是每个像素的亮度值,平均 PIL 的直方图并将亮度函数应用于输出似乎是该库的最佳方法。

If using ImageMagick (with the PythonMagick bindings), I would suggest using the identify command with the "verbose" option set.如果使用ImageMagick (使用PythonMagick绑定),我建议使用带有“verbose”选项集的识别命令。 This will provide you with a mean value for each channel, saving you the need to sum and average a histogram — you can just multiply each channel directly.这将为您提供每个通道的平均值,使您无需对直方图求和和求平均值——您可以直接将每个通道相乘。

I think your best result would come from converting the RGB to grayscale using your favorite formula, then taking the histogram of that result.我认为您最好的结果是使用您最喜欢的公式将 RGB 转换为灰度,然后获取该结果的直方图。 I'm not sure if the mean or the median of the histogram would be more appropriate, but on most images they are probably similar.我不确定直方图的均值或中值是否更合适,但在大多数图像上它们可能相似。

I'm not sure how to do the conversion to grayscale in PIL using an arbitrary formula, but I'm guessing it's possible.我不确定如何使用任意公式在 PIL 中转换为灰度,但我猜这是可能的。

the code below will give you the brightness level of an image from 0-10下面的代码将为您提供 0-10 图像的亮度级别

1- calculate the average brightness of the image after converting the image to HSV format using opencv. 1-使用opencv将图像转换为HSV格式后计算图像的平均亮度。

2- find where this value lies in the list of brightness range. 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())))

This can be done by converting the BGR image from cv2 to grayscale and then finding the intensity - x and y are pixel coordinates.这可以通过将 BGR 图像从 cv2 转换为灰度,然后找到强度 - x 和 y 是像素坐标来完成。 It's been explained well in thishttps://docs.opencv.org/3.4/d5/d98/tutorial_mat_operations.html document.在这个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