使用Python分析图像亮度的方法有哪些?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3490727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are some methods to analyze image brightness using Python?
提问by cmcginty
I'd like some advice on performing a simple image analysis in python. I need to calculate a value for the "brightness" of an image. I know PILis the goto library for doing something like this. There is a built-in histogram function.
我想要一些关于在 python 中执行简单图像分析的建议。我需要计算图像“亮度”的值。我知道PIL是执行此类操作的 goto 库。有一个内置的直方图功能。
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 值,然后应用“感知亮度”公式。
采纳答案by cmcginty
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. Also, all methods run about the same speed except for the last one, which is much slower depending on the image size.
每个方法都返回一个 close 值,但与其他方法不完全相同。此外,除最后一种方法外,所有方法的运行速度大致相同,后者根据图像大小慢得多。
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]Convert image to greyscale, return RMS pixel brightness.
def brightness( im_file ): im = Image.open(im_file).convert('L') stat = ImageStat.Stat(im) return stat.rms[0]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))RMS of pixels, then transform to "perceived brightness".
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))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]
将图像转换为灰度,返回平均像素亮度。
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]
Update Test ResultsI ran a simulation against 200 images. I found that methods #2, #4 gave almost identical results. Also methods #3, #5 were also nearly identical. Method #1 closely followed #3, #5 (with a few exceptions).
更新测试结果我对 200 张图像进行了模拟。我发现方法#2、#4 给出了几乎相同的结果。此外,方法#3、#5 也几乎相同。方法#1 紧随#3、#5(有几个例外)。
回答by Andrew
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 PythonMagickbindings), I would suggest using the identifycommand with the "verbose" option set. 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.
如果使用ImageMagick(使用PythonMagick绑定),我建议使用带有“verbose”选项集的识别命令。这将为您提供每个通道的平均值,使您无需对直方图求和和求平均值——您可以直接将每个通道相乘。
回答by Mark Ransom
I think your best result would come from converting the RGB to grayscale using your favorite formula, then taking the histogram of that result. 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.
我认为您最好的结果是使用您最喜欢的公式将 RGB 转换为灰度,然后获取该结果的直方图。我不确定直方图的均值或中值是否更合适,但在大多数图像上它们可能相似。
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 中转换为灰度,但我猜这是可能的。
回答by Ankit Gupta
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())))

