【问题标题】:Convert an image RGB->Lab with python使用 python 转换图像 RGB->Lab
【发布时间】:2012-11-04 13:13:03
【问题描述】:

目前使用 PIL/Numpy/SciPy 进行转换的首选方式是什么?

【问题讨论】:

  • 我已经阅读了这个问题stackoverflow.com/questions/3228361/…,它提供了一个指向 color.py 的断开链接,该链接从 scipy 主干中丢失。
  • 是的,我在 scipy git 存储库的深处找到了这个文件,但我不敢相信没有使用如此强大的工具来完成如此简单的事情的标准方法。
  • 是的,我知道 code.google.com/p/python-colormath lib,但我不明白为什么它没有进入这三个工具中的任何一个。

标签: python numpy scipy python-imaging-library color-space


【解决方案1】:

编辑:示例 pyCMS 代码:

from PIL import Image
import pyCMS
im = Image.open(...)
im2 = pyCMS.profileToProfile(im, pyCMS.createProfile("sRGB"), pyCMS.createProfile("LAB"))

编辑:Pillow,PIL fork,似乎内置了 pyCMS。

您可以使用 pyCMS (http://www.cazabon.com/pyCMS/) 来处理 PIL 图像。

如果速度不是一个因素,请使用 python-colormath (http://code.google.com/p/python-colormath/)。

【讨论】:

  • pyCMS 处理 ICC 配置文件,色彩空间是“副作用”。我要了一条单线。
  • 是的,我在对这个问题的第三条评论中提到了 python-colormath。
  • Anthony,但是您说它不是单个矩阵是正确的,因为 xyz->lab 变换在 xyz 的不同范围内定义不同。好吧,我不认为有一个单行,没有先将 colormath 的相关部分移植到 numpy :)
  • 问题不是 如果 有一个单行(我的 cmets 中给出了两个问题),而是 为什么 这些都不是如果有更好的选择,两个找到了进入 PIL/numpy/scipy 的方式。
  • 此外,没有必要将 colormath“移植”到 numpy,因为它从一开始就使用 numpy。
【解决方案2】:

自 2010 年以来,当询问 linked question 时,相应的代码从 scipy 移至单独的工具包: http://scikit-image.org/

所以这是我真正要寻找的代码:

from skimage import io, color
rgb = io.imread(filename)
lab = color.rgb2lab(rgb)

还需要注意的是,由于Lab性质srgb->lab转换依赖于一个额外的参数:whitepoint,例如:
Photoshop 使用称为 D50 的白点(这是 icc 的标准)
OpenCV 和 skimage 使用 D65(这是 srgb 的标准)。
• 默认Matlab实现使用D50(它能够使用others),

这个不错的FAQ是这样解释的:

除非你有充分的理由使用某物,否则你应该使用 D65 其他。
印刷行业常用D50,摄影常用 使用 D55。
这些代表了室内条件之间的妥协 (钨丝)和日光观察。

您可以通过将 RGB (0,0,255) 转换为 Lab 来判断您正在处理的白点:
• D50 会给你 (30, 68, -112)
• D55                   (30, 73, -110)
• D65                  (32, 79, -108)

“D”后面的数字对应(内部)使用的白点色温:D50 = 5003 K(偏黄),D65 = 6504 K(偏蓝)

感谢 Alex 和 Roman 的回答,因为他们为我指明了正确的方向。

【讨论】:

【解决方案3】:

我在旧的Adobe Cookbook site 上找到了这段代码,并且已经适应了 Python。它不需要任何第三方模块或组件:

def rgb2lab ( inputColor ) :

   num = 0
   RGB = [0, 0, 0]

   for value in inputColor :
       value = float(value) / 255

       if value > 0.04045 :
           value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
       else :
           value = value / 12.92

       RGB[num] = value * 100
       num = num + 1

   XYZ = [0, 0, 0,]

   X = RGB [0] * 0.4124 + RGB [1] * 0.3576 + RGB [2] * 0.1805
   Y = RGB [0] * 0.2126 + RGB [1] * 0.7152 + RGB [2] * 0.0722
   Z = RGB [0] * 0.0193 + RGB [1] * 0.1192 + RGB [2] * 0.9505
   XYZ[ 0 ] = round( X, 4 )
   XYZ[ 1 ] = round( Y, 4 )
   XYZ[ 2 ] = round( Z, 4 )

   XYZ[ 0 ] = float( XYZ[ 0 ] ) / 95.047         # ref_X =  95.047   Observer= 2°, Illuminant= D65
   XYZ[ 1 ] = float( XYZ[ 1 ] ) / 100.0          # ref_Y = 100.000
   XYZ[ 2 ] = float( XYZ[ 2 ] ) / 108.883        # ref_Z = 108.883

   num = 0
   for value in XYZ :

       if value > 0.008856 :
           value = value ** ( 0.3333333333333333 )
       else :
           value = ( 7.787 * value ) + ( 16 / 116 )

       XYZ[num] = value
       num = num + 1

   Lab = [0, 0, 0]

   L = ( 116 * XYZ[ 1 ] ) - 16
   a = 500 * ( XYZ[ 0 ] - XYZ[ 1 ] )
   b = 200 * ( XYZ[ 1 ] - XYZ[ 2 ] )

   Lab [ 0 ] = round( L, 4 )
   Lab [ 1 ] = round( a, 4 )
   Lab [ 2 ] = round( b, 4 )

   return Lab

【讨论】:

  • 它没有直接回答这个问题:我需要一个单线。但无论如何它是有帮助的。谢谢!
  • 虽然我会参考原始的 easyrgb 网站而不是 adobe 食谱。
  • 我应该说你的代码不是很pythonic。至少我会使用enumerate 而不是num 变量和1/3. 而不是0.3333333333333333
  • 此代码似乎进行了伽马校正 (** 2.4)。如果我知道我的 gamma 是 2.2 而不是 2.4 怎么办?将指数更改为 2.2 是否足够,或者是否需要更改其他硬编码常量(如 1.055)?
  • @jez 您在此处看到的 gamma 2.4 是 sRGB 标准。它与较低值的线性转换结合在一起,并且它们紧密匹配 2.2 伽马曲线。我不会改变任何东西。
【解决方案4】:

目前我还没有找到一个好的包来做到这一点。您必须记住,RGB 是依赖于设备的色彩空间,因此如果您没有配置文件,您将无法准确地转换为 XYZ 或 CIE Lab。

因此请注意,在您看到从 RGB 转换为 CIE Lab 且未指定色彩空间或导入颜色配置文件的许多解决方案必须经过仔细评估。大多数情况下,看看引擎盖下的代码,他们认为您正在处理 sRGB 颜色空间。

【讨论】:

    【解决方案5】:

    这是一个类,用于为 PIL 图像转换 RGBLAB 颜色空间:

    from PIL import ImageCms
    
    class ColorTrans:
    
        '''Class for transforming RGB<->LAB color spaces for PIL images.'''
        
        def __init__(self):
            self.srgb_p = ImageCms.createProfile("sRGB")
            self.lab_p  = ImageCms.createProfile("LAB")
            self.rgb2lab_trans = ImageCms.buildTransformFromOpenProfiles(srgb_p, lab_p, "RGB", "LAB")
            self.lab2rgb_trans = ImageCms.buildTransformFromOpenProfiles(lab_p, srgb_p, "LAB", "RGB")
        
        def rgb2lab(self, img):
            return ImageCms.applyTransform(img, self.rgb2lab_trans)
    
        def lab2rgb(self, img):
            return ImageCms.applyTransform(img, self.lab2rgb_trans)
    

    示例用法:

    color_trans = ColorTrans()
    c_img = Image.open(FILENAME)
    c_img_lab = color_trans.rgb2lab(c_img)
    c_img_rgb = color_trans.lab2rgb(c_img_lab)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-14
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 1970-01-01
      相关资源
      最近更新 更多