色彩空间

色彩空间在物体追踪、特征检测等(简单来说就是识别一个东西)扮演着很重要的角色。毕竟每个物体都有特定的颜色和特征,我们可以应用其物体与环境颜色上的差异,从图像中提取特定范围的颜色并加上一些逻辑性的判断,获取待检测物体的位置。

颜色

colors
上图可见的是一些常见的颜色,我们人眼一看并可辨认是什么颜色。但是在计算机信息上,我们该如何去定义或描述这些颜色呢?这就是颜色空间的作用了。不同的颜色空间以不同的方式去定义各个颜色,同样的颜色在不同的颜色空间有着不同的值,这是因为每一个颜色空间都有不同的性质。以下我们讨论并比较颜色空间在图像分割上的一些性质。

不同的色彩空间

在本节中,我们将介绍计算机视觉中使用的一些重要色彩空间。我们不会描述它们背后的理论,因为可以在Wikipedia上找到它。相反,我们将发展一个基本的直觉并学习一些重要的属性,这些属性对于以后的决策很有用。

让我们加载2个相同立方体的图像,如下所示。默认情况下,它将以BGR格式加载。 Mat bright = imread("cube1.jpg");
Mat dark = imread("cube8.jpg");

两张在不同明亮度拍摄的魔方照片

下面我们要从不同的颜色空间分析这例子图像的颜色性质。从常用到非常用,我会介绍:
最后我顺带介绍灰度图(Grayscale)

我们可以使用OpenCV函数cvtColor()在不同的色彩空间之间进行转换。例: cv::cvtColor(input_img, output_img, cv::COLOR_BGR2LAB); //从BGR转LAB cv::cvtColor(input_img, output_img, cv::COLOR_BGR2HSV); //从BGR转HSV cv::cvtColor(input_img, output_img, cv::COLOR_BGR2YCrCb); //从BGR转YCrCb


BGR色彩空间


BGR色彩空间
我制作了个简单的颜色拉条,可以手动尝试每个颜色通道对颜色的关系。
BGR色彩空间具有以下属性

取值范围

在OpenCV中,BGR的取值范围(默认的CV_8U格式)为:
0 >= B >= 255
0 >= G >= 255
0 >= R >= 255
某个通道的值越高,代表那个性质是越高的,反之亦然。如,R通道的值越高,那个像素颜色就越红。

让我们将两个图像的B,G和R通道分离,然后观察。

RGB色彩空间的不同通道蓝色(B),绿色(G),红色(R)分别显示

观察结果

如果你查看蓝色通道,可以看到在室内照明条件下,第二张图像中的蓝色和白色部分看起来相似,但是第一张图像中有明显的不同。这种不均匀性使得在这种颜色空间中基于颜色的分割非常困难。此外,两个图像的值之间存在整体差异。下面我们总结下与RGB颜色空间相关的固有问题:


HSV色彩空间

HSV颜色空间具有以下三个组成部分 让我们列举一下它的一些属性。

取值范围

在OpenCV中,HSV的取值范围(默认的CV_8U格式)为:
0 >= H >= 360 ⇒ OpenCV range = H/2 (0 >= H >= 180)
0 >= S >= 1 ⇒ OpenCV range = 255*S (0 >= S >= 255)
0 >= V >= 1 ⇒ OpenCV range = 255*V (0 >= V >= 255)
这两个图像的H,S和V分量如下所示。 analysis_hsv.cpp ... Mat brightHSV, darkHSV; // 转换颜色空间 cvtColor(bright, brightHSV, COLOR_BGR2HSV); cvtColor(dark, darkHSV, COLOR_BGR2HSV); Mat bright_hsv[3]; split(brightHSV, bright_hsv); // 通道分离 Mat dark_hsv[3]; split(darkHSV, dark_hsv); // 通道分离 String c[3] = {"H", "S", "V"}; for (int i=0; i<3; i++) { imshow("bright " + c[i], bright_hsv[i]); } for (int i=0; i<3; i++) { imshow("dark " + c[i], dark_hsv[i]); } waitKey(0); destroyAllWindows(); ...

HSV颜色空间中的色相(H),饱和度(S)和值(V)分量

观察结果

两个图像中的H分量非常相似,这表明即使在光照变化下颜色信息也完整无缺。
在两个图像中,S分量也非常相似。
V分量捕获落在其上的光量,因此由于照明的变化而发生变化。
室外红色图像和室内图像的红色值之间存在巨大差异。这是因为色相H为轮(0度到360度),红色表示起始角度。因此,它可能取[300,360]到[0,60]之间的值。


LAB颜色空间


LAB色彩空间
Lab颜色空间包含三个组成部分。 Lab颜色空间与RGB颜色空间完全不同。在RGB颜色空间中,颜色信息分为三个通道,但是相同的三个通道中也包含亮度信息。而在Lab颜色空间中,L通道与颜色信息无关,并且仅包含亮度信息,其他两个通道对颜色进行编码。

它具有以下属性。

取值范围

在OpenCV中,Lab的取值范围(默认的CV_8U格式)为:
0 >= L >= 100 ⇒ OpenCV range = L*255/100 (1 >= L >= 255)
-127 >= a >= 127 ⇒ OpenCV range = a + 128 (1 >= a >= 255)
-127 >= b >= 127 ⇒ OpenCV range = b + 128 (1 >= b >= 255)
让我们查看Lab颜色空间中的两个图像,这些图像分为三个通道。 analysis_lab.cpp ... Mat brightLAB, darkLAB; // 转换颜色空间 cvtColor(bright, brightLAB, COLOR_BGR2LAB); cvtColor(dark, darkLAB, COLOR_BGR2LAB); Mat bright_lab[3]; split(brightLAB, bright_lab); // 通道分离 Mat dark_lab[3]; split(darkLAB, dark_lab); // 通道分离 String c[3] = {"L", "a", "b"}; for (int i=0; i<3; i++) { imshow("bright " + c[i], bright_lab[i]); } for (int i=0; i<3; i++) { imshow("dark " + c[i], dark_lab[i]); } waitKey(0); destroyAllWindows(); ...

LAB颜色空间中的亮度(L)和颜色分量(A,B)。

观察结果

从图中可以很明显地看出,亮度的变化主要影响了L分量。
包含颜色信息的A和B组件没有发生大的变化。
在两图中,绿色、红色和橙色在B值上区别不大(而在A值上却是极端),蓝色和黄色在A值上区别不大(而在B值上却是极端)


YCrCb颜色空间


YCrCb颜色空间
YCrCb颜色空间是从RGB颜色空间派生的,并且具有以下三个组件。
equation
RGB转换成YCrCb的方程
此色彩空间具有以下属性。 YCrCb颜色空间中的两个图像分为两个通道,如下所示 analysis_ycrcb.cpp ... Mat brightYCrCb, darkYCrCb; // 转换颜色空间 cvtColor(bright, brightYCrCb, COLOR_BGR2YCrCb); cvtColor(dark, darkYCrCb, COLOR_BGR2YCrCb); Mat bright_ycrcb[3]; split(brightYCrCb, bright_ycrcb); // 通道分离 Mat dark_ycrcb[3]; split(darkYCrCb, dark_ycrcb); // 通道分离 String c[3] = {"Y", "Cr", "Cb"}; for (int i=0; i<3; i++) { imshow("bright " + c[i], bright_ycrcb[i]); } for (int i=0; i<3; i++) { imshow("dark " + c[i], dark_ycrcb[i]); } waitKey(0); destroyAllWindows(); ...

YCrCb颜色空间中的亮度(Y)和色度(Cr,Cb)分量

观察结果

和LAB一样,亮度Y会受到光线影响,而颜色成分Cr和Cb不会受到光线影响。
与LAB相比,即使在室外图像中,红色和橙色之间的感知差异也较小。
白色在三个颜色通道有不一样的值。


灰度图(Grayscale)

单通道图像我们称为灰度图。它只包含图像的光度信息,并没有颜色信息。所以我们在显示灰度图时一定是只有“灰色”。
我们可以一样使用cvtColor变换图像成灰度图。常用的用法为: cvtColor(img, gray, COLOR_BGR2GRAY); 我们也可以在读取图像时先“下手为强”。可以在第二个参数填上IMREAD_GRAYSCALE或0,将会返回一个单通道灰度图。用法:
img = imread("path/to/img.jpg", IMREAD_GRAYSCALE);

取值范围

在OpenCV中,灰度图的取值范围(默认的CV_8U格式)为:
0 ~ 255