使用PIL(RGB转LAB)与OpenCV(BGR转LAB)图像转换结果差异原因
问题:PIL与OpenCV转换LAB颜色空间数值差异极大的原因
使用PIL和OpenCV读取同一张PNG图像,执行以下代码后,得到的LAB通道数值差异显著,但RGB/BGR通道数据完全一致:
测试代码
# PIL + skimage from PIL import Image import numpy as np from skimage import color img = Image.open(path_img) lab = np.uint8(color.rgb2lab(img)) # OpenCV import cv2 img_cv2 = cv2.imread(path_img) lab_cv2 = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2LAB)
通道1(a通道)输出对比
PIL+skimage输出:
img lab PIL [[ 3 2 2 ... 0 0 0] [ 3 1 1 ... 0 0 0] [ 2 2 2 ... 0 0 0] ... [ 0 0 0 ... 1 0 0] [ 0 255 255 ... 0 0 0] [ 0 0 1 ... 1 1 0]]
OpenCV输出:
img lab cv2 [[132 132 130 ... 130 130 128] [132 132 132 ... 130 128 128] [132 130 130 ... 130 128 130] ... [130 128 130 ... 129 129 128] [128 128 128 ... 128 128 129] [128 128 130 ... 129 129 128]]
RGB通道验证(数据一致)
测试代码:
print("r channel img PIL", np.uint8(img)[:, :, 0]) print("r channel img cv2", img_cv2[:, :, 2])
PIL的R通道输出:
img lab PIL [[29 31 29 ... 2 1 0] [29 28 30 ... 1 0 1] [28 29 30 ... 2 2 1] ... [19 18 20 ... 57 51 53] [14 18 17 ... 60 57 54] [15 17 19 ... 58 57 49]]
OpenCV的R通道输出:
img lab cv2 [[29 31 29 ... 2 1 0] [29 28 30 ... 1 0 1] [28 29 30 ... 2 2 1] ... [19 18 20 ... 57 51 53] [14 18 17 ... 60 57 54]
原因分析
差异来自两个库对LAB颜色空间的数值范围定义不同,以及转换前的输入数据预处理规则差异:
输入数据的归一化差异
skimage.color.rgb2lab要求输入RGB数据为0-1范围的浮点型,若输入是0-255的uint8类型,会自动将数值归一化到0-1区间后再转换。- OpenCV的
cv2.cvtColor直接处理0-255的uint8型数据,无需额外归一化,直接基于原始像素值完成转换。
LAB通道的数值缩放偏移规则不同
- 标准LAB颜色空间的数值范围:L∈[0,100],a∈[-128,127],b∈[-128,127]。
skimage.color.rgb2lab输出原始范围的LAB值:L在0-100,a和b在-128到127之间。你用np.uint8()强制转换时,负数会被截断为0,超过255的数值被截断为255,这就导致a通道出现大量0-3的数值,个别255对应原始a值接近-128的情况。- OpenCV的
cv2.COLOR_BGR2LAB会自动对LAB数值做偏移缩放:将L范围映射到[0,255],a和b范围从[-128,127]偏移为[0,255](即每个值加128)。所以你看到的a通道数值集中在128左右,和skimage的原始a值一一对应(比如OpenCV的132=skimage的4+128,128=skimage的0+128)。
统一输出的方法
若要让两者输出一致,可做如下处理:
- 对skimage的结果做偏移缩放,匹配OpenCV格式:
lab_sk_scaled = np.uint8(np.stack([lab[...,0]*2.55, lab[...,1]+128, lab[...,2]+128], axis=-1)) - 对OpenCV的结果做反向偏移,得到标准LAB范围:
lab_cv_unscaled = np.stack([lab_cv2[...,0]/2.55, lab_cv2[...,1]-128, lab_cv2[...,2]-128], axis=-1)
内容的提问来源于stack exchange,提问作者Rita Carvalho
相关产品推荐
相关产品推荐

