如何将RGB图像像素转换为L*a*b*?

Tec*_*Net 7 python image pixel image-processing

好吧,我正在使用图像处理来识别图像的颜色变化并能够在直方图中绘制该数据。为此,我使用 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
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 8

您可以使用内置的颜色管理系统和 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)
Run Code Online (Sandbox Code Playgroud)

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')
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

你会得到这个作为L频道:

在此处输入图片说明

这是a频道:

在此处输入图片说明

这是b频道:

在此处输入图片说明

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

L = 0.2*R + 0.7*G + 0.1*B
Run Code Online (Sandbox Code Playgroud)

因此,您会期望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)
Run Code Online (Sandbox Code Playgroud)

我不是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
Run Code Online (Sandbox Code Playgroud)