将 OpenCV BGR 8 位图像转换为 CIE L*a*b*
Posted
技术标签:
【中文标题】将 OpenCV BGR 8 位图像转换为 CIE L*a*b*【英文标题】:Converting an OpenCV BGR 8-bit Image to CIE L*a*b* 【发布时间】:2012-07-08 08:24:03 【问题描述】:我正在尝试使用文档中提供的函数将代表具有 8 位深度的 RGB 图像的给定 Mat
转换为 Lab:
cvtColor(source, destination, <conversion code>);
我尝试了以下转换代码:
CV_RGB2Lab
CV_BGR2Lab
CV_LBGR2Lab
我每次都收到奇怪的结果,某些样本的“L”值大于 100,字面意思是 。
我也在使用 Photoshop 来检查结果 - 但鉴于 107 超出了 0 ≤ L ≤ 100 的可接受范围,我无法理解我的错误是什么。
更新: 我将在这里发布我的总体结果: 给定一张由 8 位 BGR 表示的图像(Mat),图像可以通过以下方式进行转换:
cvtColor(source, destination, CV_BGR2Lab);
然后可以通过以下方式访问像素值:
int step = destination.step;
int channels = destination.channels();
for (int i = 0; i < destination.rows(); i++)
for (int j = 0; j < destination.cols(); j++)
Point3_<uchar> pixelData;
//L*: 0-255 (elsewhere is represented by 0 to 100)
pixelData.x = destination.data[step*i + channels*j + 0];
//a*: 0-255 (elsewhere is represented by -127 to 127)
pixelData.y = destination.data[step*i + channels*j + 1];
//b*: 0-255 (elsewhere is represented by -127 to 127)
pixelData.z = destination.data[step*i + channels*j + 2];
【问题讨论】:
此外,在不知道颜色配置文件的情况下,您无法以可靠的结果进行 RGB 到 Lab 转换。 RGB 不是独立的色彩空间,Lab 是。 【参考方案1】:如果有人遇到同样的问题:
请注意,在 OpenCV (2.4.13) 中,您可以不将 CV_32FC3 BGR 图像转换为 Lab 颜色空间。也就是说:
//this->xImage is CV_8UC3
this->xImage.convertTo(FloatPrecisionImage, CV_32FC3);
Mat result;
cvtColor(FloatPrecisionImage, result, COLOR_BGR2Lab);
this->xImage = result;
将不工作 而
Mat result;
cvtColor(this->xImage, result, COLOR_BGR2Lab);
result.convertTo(this->xImage, CV_32FC3);
像魅力一样工作。 我没有追查上述行为的原因;然而,在我看来,这似乎对图像质量造成了限制。
【讨论】:
【参考方案2】:我不确定 João Abrantes 在 A 和 B 上的范围。
opencv documentation 明确提到了CIE L*a*b*
范围。
8 位图像
从而导致一个范围
0 <= L <= 255
0 <= a <= 255
0 <= b <= 255
【讨论】:
【参考方案3】:如果有人对其他变量a
和b
的范围感兴趣,我编写了一个小程序来测试它们的范围。
如果将所有用 RGB 表示的颜色转换为 OpenCV 中使用的 CieLab,则范围为:
0 <=L<= 255
42 <=a<= 226
20 <=b<= 223
如果您在浮点模式下使用 RGB 值而不是 uint8,则范围将为:
0.0 <=L<= 100.0
-86.1813 <=a<= 98.2352
-107.862 <=b<= 94.4758
附:如果您想了解一个 LAB 值与另一个 LAB 值的区别(关于人类感知),您应该使用浮点数。用于将实验室值保持在 uint8 范围内的比例与其欧几里德距离相混淆。
这是我使用的代码(python):
L=[0]*256**3
a=[0]*256**3
b=[0]*256**3
i=0
for r in xrange(256):
for g in xrange(256):
for bb in xrange(256):
im = np.array((bb,g,r),np.uint8).reshape(1,1,3)
cv2.cvtColor(im,cv2.COLOR_BGR2LAB,im) #tranform it to LAB
L[i] = im[0,0,0]
a[i] = im[0,0,1]
b[i] = im[0,0,2]
i+=1
print min(L), '<=L<=', max(L)
print min(a), '<=a<=', max(a)
print min(b), '<=b<=', max(b)
【讨论】:
为什么用欧几里得距离说 uint8 类型“混乱”中的 LAB 值的比例? @simplename LAB 的想法是,两种颜色的欧几里得距离与人眼区分这两种颜色的难易程度有关。使用 uint8,L 幅度现在是 255 而不是 100,而 a 和 b 仍然具有相似的范围 - 当使用 uint8 或使用浮点数时,两种不同的颜色具有不同的欧几里得距离。 我似乎无法转换为原始图像 -> float32 -> bgr2lab -> 进行更改 -> lab2bgr -> uint8 -> 没有问题的新图像。你有来回转换的代码吗?【参考方案4】:这是因为 L 值在 OpenCV 中的 [0..255] 范围内。您可以简单地将此值缩放到所需的间隔(在您的情况下为 [0..100])。
【讨论】:
以上是关于将 OpenCV BGR 8 位图像转换为 CIE L*a*b*的主要内容,如果未能解决你的问题,请参考以下文章
Python OpenCV - imshow 不需要从 BGR 转换为 RGB
如何使用 OpenCV C++ 将 24 位深度的 PNG 图像转换为 8 位深度的 PNG 图像