【问题标题】:Getting RGB Values of Pixels Based on Luminance in Python在 Python 中根据亮度获取像素的 RGB 值
【发布时间】:2020-07-20 06:19:48
【问题描述】:

试图弄清楚如何完成这项任务:我想根据亮度选择图像的像素,然后获取这些像素的 rgb 值。

我最初的想法是使用OpenCV在图像的灰度上做一个直方图:

img = cv2.imread('test.jpg',0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])

但我不确定如何确定直方图特定 bin 中的像素在图像中的位置?

另外,我找到了这个公式来获得亮度:

(0.2126*R + 0.7152*G + 0.0722*B)

所以我想我可以使用该公式遍历图像中的所有像素并获取与我选择的亮度级别相匹配的像素?

有没有更好的方法在 Python 中实现这一点?

【问题讨论】:

  • 是的,更好的方法是避免循环和迭代 Python 中的像素/图像。使用 Numpy、Scipy 或 OpenCV,但尽可能不要使用 for 循环。
  • 通过 cv2.cvt() 从您的输入计算亮度图像,这可能只是转换为灰色或为您的亮度公式找到 BGR2...。您想要的亮度范围的阈值。见 cv2.inRange()。然后通过 numpy np.where 将阈值图像应用于您的图像,以从输入中获取阈值图像白色下方的所有像素。
  • 如果您可以更具体一点,您可能会得到更多帮助...例如,您是否有示例输入和输出图像?您能否更具体地了解匹配像素所涉及的“抓取” - 您的意思是制作一个列表来排序和查找独特的颜色,还是屏蔽它们并仅在黑色背景上显示它们...... ?谢谢。

标签: python image-processing rgb luminance


【解决方案1】:

首先,虽然系数对于 sRGB 或 Rec709 是正确的,但要从颜色转换为 Y...

    (0.2126*R + 0.7152*G + 0.0722*B)

...他们要求 RGB 通道全部线性化以移除任何伽马编码。

其次,这些是 Rec709 或 sRGB 的系数,但其他色彩空间需要不同的系数。

图书馆

我推荐 KenSolaar 的 ColourScience,这是一个 python 库,可以执行转换为亮度等操作,并使用 numpy 和矢量化数学。

https://github.com/colour-science/colour

转换和跟踪像素值

将 sRGB 像素转换为亮度非常简单:

  1. 将 sRGB 值解析为离散的 RʹGʹBʹ 值。我们假设是 8 位。
  2. 分别除以 255.0
  3. 移除 TRC(又名伽玛)。
    • sRGB 和其他几个色彩空间的简单方法是使用 ^2.2 的指数将功率曲线应用于每个 RʹGʹBʹ 通道。
  4. 然后对亮度 Y 应用系数和总和。
    • (0.2126 * R + 0.7152 * G + 0.0722 * B)

将所有这些放在一起:

    imgPixel = 0xAACCFF

    R = (imgPixel & 0xFF0000) >> 16
    G = (imgPixel & 0x00FF00) >> 8
    B = (imgPixel & 0x0000FF)

    Y = 0.2126*(R/255.0)**2.2 + 0.7152*(G/255.0)**2.2 + 0.0722*(B/255.0)**2.2 

这是最简单的,但仍然相当准确,但是一些纯粹主义者可能会建议使用 IEC 指定的 sRGB TRC,它是分段且计算成本更高的:

# Piecewise sRGB TRC to Linear (only red is shown in this example)

    if R <= 0.04045:
       R / 12.92
    else: 
    (( R + 0.055) / 1.055) ** 2.4

是吗?

下一个问题是,如何确定像素,这只是创建并填充一个列表(数组),其中包含与亮度匹配的像素的坐标和颜色值。

您想将亮度量化回 8 位整数值吗?还是停留在 0.0 到 1.0 并定义一个范围?后者通常最有用,所以让我们这样做。

对于cv2.imread('test.jpg',1),不要将标志设置为 0 — 您将制作自己的灰度并且想要保存颜色像素值,对吗?

因此使用前面的示例,但使用三元分段 TRC 方法并添加一个循环,为找到的像素附加一个数组:

          # declare some variables
    Llo = 0.18  # Lo luminance range
    Lhi = 0.20  # Hi range choosing pixels between here and Lo
    results = [[]]
    imgPixel = 0x000000
    
    img = cv2.imread('test.jpg',1) # set flag to 1 (or omit) for color — you're going to make your own greyscale.

    rows,cols = img.shape

    for ir in range(rows):
      for ic in range(cols):
         imgPixel = img[ir,ic]
         
         R = ((imgPixel & 0xFF0000) >> 16) / 255.0
         G = ((imgPixel & 0x00FF00) >> 8 ) / 255.0
         B = ((imgPixel & 0x0000FF)      ) / 255.0

         R = R / 12.92 if R <= 0.04045 else (( R + 0.055) / 1.055) ** 2.4
         G = G / 12.92 if G <= 0.04045 else (( G + 0.055) / 1.055) ** 2.4
         B = B / 12.92 if B <= 0.04045 else (( B + 0.055) / 1.055) ** 2.4

         Y = 0.2126 * R + 0.7152 * G + 0.0722 * B

            # If the Y is in range, then append the pixel coordinates and color value to the array
         if Y>Llo or Y<Lhi: results.append([ ic, ir, imgPixel ])

# CAVEAT: This code is entered but not tested in Python.

很可能有一种方法可以将其矢量化,因此值得查看我上面链接的颜色科学库,因为它尽可能这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多