【问题标题】:How to convert RGB image pixels to L*a*b*?如何将 RGB 图像像素转换为 L*a*b*?
【发布时间】:2019-03-16 23:08:45
【问题描述】:

嗯,我正在使用图像处理来识别图像的颜色变化,并能够在直方图中绘制该数据。为此,我使用 RGB 颜色空间中的皮肤斑点图像。下面的代码我可以获取每个像素的颜色并使用 color.rgb2lab 转换为 HSV。但是由于我想转换为L*a*b*,因为它更接近人类视觉,所以在python库中没有转换为L*a*b*。有了这个,通过RGB的分离像素,我如何将这些像​​素转换成LAB颜色?

import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.pyplot as plt
import colorsys
from PIL import Image

# (1) Import the file to be analyzed!
img_file = Image.open("IMD006.png")
img = img_file.load()

# (2) Get image width & height in pixels
[xs, ys] = img_file.size
max_intensity = 100
hues = {}

# (3) Examine each pixel in the image file
for x in xrange(0, xs):
  for y in xrange(0, ys):
    # (4)  Get the RGB color of the pixel
    [r, g, b] = img[x, y]

# (5)  Normalize pixel color values
r /= 255.0
g /= 255.0
b /= 255.0

# (6)  Convert RGB color to HSV
[h, s, v] = colorsys.rgb_to_hsv(r, g, b)

# (7)  Marginalize s; count how many pixels have matching (h, v)
if h not in hues:
  hues[h] = {}
if v not in hues[h]:
  hues[h][v] = 1
else:
  if hues[h][v] < max_intensity:
    hues[h][v] += 1

【问题讨论】:

标签: python image image-processing pixel


【解决方案1】:

您可以使用 PIL/Pillow 使用内置的颜色管理系统并构建如下变换:

#!/usr/local/bin/python3

import numpy as np
from PIL import Image, ImageCms

# Open image and discard alpha channel which makes wheel round rather than square
im = Image.open('colorwheel.png').convert('RGB')

# Convert to Lab colourspace
srgb_p = ImageCms.createProfile("sRGB")
lab_p  = ImageCms.createProfile("LAB")

rgb2lab = ImageCms.buildTransformFromOpenProfiles(srgb_p, lab_p, "RGB", "LAB")
Lab = ImageCms.applyTransform(im, rgb2lab)

Lab 现在是您在 Lab 色彩空间中的图像。如果继续在上述代码的末尾添加以下行,则可以将 Lab 图像拆分为其组成通道,并将它们分别保存为灰度图像以供检查。

# Split into constituent channels so we can save 3 separate greyscales
L, a, b = Lab.split()

L.save('L.png')
a.save('a.png')
b.save('b.png')

所以,如果你从这张图片开始:

你会得到这个L频道:

这是a频道:

这是b频道:

暂时不科学,a 通道在图像为绿色时应为负/低,在图像为洋红色时应为高/正,因此看起来正确。 b 通道应该是负/低,图像是蓝色,高/正,图像是黄色,所以对我来说看起来不错!至于L 通道,RGB 到灰度的公式(在我的脑海中)类似于:

L = 0.2*R + 0.7*G + 0.1*B

因此,您会期望L 通道在图像为绿色的地方更亮,在图像为蓝色的地方最暗。


或者,您可以使用 scikit-image 模块来实现,甚至可以更简单地像这样:

import numpy as np
from skimage import color, io

# Open image and make Numpy arrays 'rgb' and 'Lab'
rgb = io.imread('image.png')
Lab = color.rgb2lab(rgb)

我不能 100% 确定缩放比例,但我怀疑 L 通道是 0..100 范围内的浮点数,而 ab 也是 -128..+ 范围内的浮点数128,虽然我可能错了!

通过上面的色轮图像,我得到了每个通道的以下最小值/最大值:

Lab[:,:,0].min()     # L min
32.29567256501352

Lab[:,:,0].max()     # L max
97.13950703971322

Lab[:,:,1].min()     # a min
-86.18302974439501

Lab[:,:,1].max()     # a max
98.23305386311316

Lab[:,:,2].min()     # b min
-107.85730020669489

Lab[:,:,2].max()     # b max
94.47812227647823

【讨论】:

  • 有没有办法为多个乐队做到这一点?就像我们有 RGB + 1 个波段/层一样。我们该如何处理?
  • 对于其他尝试使用 RGB->LAB->RGB 并在 LAB 空间中对像素数据进行一些调整的人:skimage 方法几乎是开箱即用的,而 ImageCms 路线要困难得多实施。
【解决方案2】:
from colormath.color_objects import sRGBColor, LabColor
from colormath.color_conversions import convert_color 

def rgb_to_cielab(a):
    """
    a is a pixel with RGB coloring
    """
    a1,a2,a3 = a/255

    color1_rgb = sRGBColor(a1, a2, a3);

    color1_lab = convert_color(color1_rgb, LabColor);

    return color1_lab

rgb_to_cielab(np.array([255,0,255]))

输出:LabColor(lab_l=60.32364943499053,lab_a=98.23532017664644,lab_b=-60.83501679458592)

【讨论】:

    【解决方案3】:

    使用 cv2 您可以轻松实现这种转换。 RGB->LAB,LAB->RGB。

    import numpy as np
    import cv2
    
    img = cv2.imread('1.jpg')
    LAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
    
    cv2.imwrite('L.png', LAB[:,:,0])
    cv2.imwrite('a.png', LAB[:,:,1])
    cv2.imwrite('b.png', LAB[:,:,2])
    
    BGR = cv2.cvtColor(LAB, cv2.COLOR_LAB2BGR)
    # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    cv2.imwrite('new.png', BGR)
    

    【讨论】:

    • 为提高答案质量提供一些背景信息。否则它会成为机器人的食物,用“低质量答案”标记它。
    • 谢谢,我会添加一些说明
    【解决方案4】:

    我已经像你一样看到这个问题 3 个月了,这是我的解决方案

    import numpy as np
    import mpl_toolkits.mplot3d.axes3d as p3
    import matplotlib.pyplot as plt
    import colorsys
    from PIL import Image
    from past.builtins import xrange
    img_file = Image.open("F:/coding/Project/FDD/neo5.png")
    img = img_file.load()
    [xs, ys] = img_file.size
    max_intensity = 100
    hues = {}
    for x in xrange(0, xs):
       for y in xrange(0, ys):
    
    [r, g, b] = img[x, y]
    r /= 255.0
    g /= 255.0
    b /= 255.0
    [h, s, v] = colorsys.rgb_to_hsv(r, g, b)
    if h not in hues:
       hues[h] = {}
    if v not in hues[h]:
       hues[h][v] = 1
    else:
       if hues[h][v] < max_intensity:
          hues[h][v] += 1
    
    h_ = []
    v_ = []
    i = []
    colours = []
    for h in hues:
       for v in hues[h]:
          h_.append(h)
          v_.append(v)
          i.append(hues[h][v])
          [r, g, b] = colorsys.hsv_to_rgb(h, 1, v)
          colours.append([r, g, b])
    
    fig = plt.figure()
    ax = p3.Axes3D(fig)
    ax.scatter(h_, v_, i, s=5, c=colours, lw=0)
    ax.set_xlabel('Hue')
    ax.set_ylabel('Value')
    ax.set_zlabel('Intensity')
    fig.add_axes(ax)
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 2012-07-08
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 2021-12-15
      • 2017-07-16
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      相关资源
      最近更新 更多