将 RGB 图像转换为 LAB 图像时出现意外输出

Unexpected output while converting RGB image to LAB image

我正在尝试提取 32 位 RGB 图像的 LAB a 通道​​。但是我没能正确读取图像,得到了意想不到的结果。

import cv2
org = cv2.imread('42.png', -1)
print org.dtype
# print uint8
lab_image = cv2.cvtColor(org, cv2.COLOR_RGB2LAB)
l,a,b = cv2.split(lab_image)
cv2.imshow('', a)
cv2.waitKey(0)

原图: http://labtools.ipk-gatersleben.de/images/42.png

预期输出(ImageJ): http://labtools.ipk-gatersleben.de/images/imagej_out.png

OpenCV 输出: http://labtools.ipk-gatersleben.de/images/python_out.png

我也试过 read/convert 用 skimage 的图像,但结果是一样的...

您的代码有几个问题。首先,正如 Miki 正确指出的那样,您必须交换红色和蓝色通道。根据 OpenCV documentation(强调我的):

Note that the default color format in OpenCV is often referred to as RGB but it is actually BGR (the bytes are reversed)

然后你需要将图像投射到float32(因为float64不被cv2.cvtColor支持)并缩小它以适应0..1范围:

In case of linear transformations, the range does not matter. But in case of a non-linear transformation, an input RGB image should be normalized to the proper value range to get the correct results, for example, for RGB → Lu*v* transformation. For example, if you have a 32-bit floating-point image directly converted from an 8-bit image without any scaling, then it will have the 0..255 value range instead of 0..1 assumed by the function. So, before calling cvtColor, you need first to scale the image down

cv2.cvtColor 返回的 a 的值被限制为 。为了改进可视化,通过从 a 中减去 a.min() 来拉伸对比度并将结果值重新缩放一个因子 255./(a.max() - a.min()) 以适应范围 0..255 是很有用的。如果这样做,您应该获得预期的结果。这是完整的代码:

import cv2
import numpy as np
org = np.float32(cv2.imread('42.png', -1))/255.
lab_image = cv2.cvtColor(org, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab_image)
a_scaled = np.uint8(255.*(a - a.min())/(a.max() - a.min()))
cv2.imshow('', a_scaled)
cv2.waitKey(0)

奖金

您可以使用 scikit-image 获得相同的 结果:

from skimage import io, color
import matplotlib.pyplot as plt

org = io.imread('http://labtools.ipk-gatersleben.de/images/42.png')
lab_image = color.rgb2lab(org)
a = lab_image[:, :, 1]

fig, ax = plt.subplots(1, 1)
plt.set_cmap('gray')
ax.imshow(a)

† 实际上,OpenCV 和 scikit-image 得出的结果并不完全相同。由于与浮点运算相关的数字错误,存在细微差异。这种差异源于 cv2.cvtColor returns 三个 float32 的 2D 数组,而 skimage.color.rgb2lab 产生 float64[ 的 3D 数组=46=].