常用彩色模型及转换

Posted 小龙呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用彩色模型及转换相关的知识,希望对你有一定的参考价值。

目录

RGB(Red、Green、Blue)彩色模型

       我们都知道在计算机中图像是以矩阵的方式存储的,而一张彩色图像的每个像素颜色是由三个数据表示的,可是为什么那么多的颜色都可以用三个数据来表示呢?
       我们来看下面这张图,假设我们所有的颜色数据可以进行归一化,那么我们就可以用这个正方体来表示所有的颜色,空间中每个向量都可以表示一个颜色,而我们可以看红色,绿色,蓝色这三个向量,正好构成了空间的一组基底。
       学过线性代数的同学都知道,我们是可以用这组基底来表示正方体中的每一个向量的,也就是每一个颜色,这样我们就可以用RGB作为三原色,构建出一个RGB彩色模型。


       RGB模型就是我们正常拍照时所能看到的彩色照片,而当我们将自己所拍的照片用opencv进行处理时,其实使用的是BGR模型,有的同学就可能会有疑问,RGB模型和BGR模型有什么区别呢?当然有区别啦,它们的顺序有区别,就是当我们用opencv读入一张图片时,我们每个像素的三个数据分别对应着B、G、R三个通道,而我们实际处理的时候去过把它当做是RGB的顺序的话,当然就会出错啦!所以我们在用opencv读入一张图片时,我们去过想用RGB模型进行处理,我们则需要转换一下模型。
       下面就是一个简单的RGB模型的例子,而且我们可以用多维数组索引切片的方法来获取其中的B、G、R三通道并显示出来。

程序实现:

import cv2
import matplotlib.pyplot as plt

imgBGR = cv2.imread("LR.jpeg", flags = 1)  # flags=1 读取彩色图像(BGR)

# 获取B通道
bImg = imgBGR.copy()  # 获取BGR
bImg[:, :, 1] = 0  # G=0
bImg[:, :, 2] = 0  # R=0

# 获取G通道
gImg = imgBGR.copy()  # 获取BGR
gImg[:, :, 0] = 0  # B=0
gImg[:, :, 2] = 0  # R=0

# 获取R通道
rImg = imgBGR.copy()  # 获取BGR
rImg[:, :, 0] = 0  # B=0
rImg[:, :, 1] = 0  # G=0

plt.subplot(231), plt.title("BGR"), plt.axis('off')
#plt.imshow()和cv2.imshow()颜色模型不一样
plt.imshow(imgBGR)  # matplotlib显示BGR

plt.subplot(233), plt.title("RGB"), plt.axis('off')
imgRGB = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2RGB)  # BGR--->RGB
plt.imshow(imgRGB)  # matplotlib显示RGB

plt.subplot(234), plt.title("B channel"), plt.axis('off')
bImg = cv2.cvtColor(bImg, cv2.COLOR_BGR2RGB)  # BGR--->RGB
plt.imshow(bImg)  # matplotlib显示channel B

plt.subplot(235), plt.title("G channel"), plt.axis('off')
gImg = cv2.cvtColor(gImg, cv2.COLOR_BGR2RGB)
plt.imshow(gImg)  # matplotlib显示channel G

plt.subplot(236), plt.title("R channel"), plt.axis('off')
rImg = cv2.cvtColor(rImg, cv2.COLOR_BGR2RGB)
plt.imshow(rImg)  # matplotlib显示channel R

plt.tight_layout() #自动调整子图间距
plt.show()

运行结果:

       注意:这个RGB就是我用手机拍的原图,当然我们可以使用cv2.show()直接显示,但是我们如果用plt.show()直接显示的话,其实会出现BGR这张图,这是为什么呢?是因为cv2.show()和plt.show()使用的颜色模型是不一样的,cv2.show()使用的是BGR模型,而读入的也是相对应的BGR模型,所以我们可以直接显示原图;但是plt.show()使用的是RGB模型,我们用opencv读入图像时,会和plt.show()使用的RGB模型通道不对应,所以会显示上面BGR这张图啦,而我们想得到RGB这张原图,就需要进行模型转换啦。

CMY和CMYK(Cyan、Magenta、Yellow、Black)彩色模型

       同样CMY模型也很好理解,只不过是用另外三个向量(一组基)来表示空间中所有的颜色而已。
       青色、深红色和黄色是光的二次色。当青色颜料涂覆的表面用白光照射时,该表面将不反射红光。也就是说,青色从反射的白光中减去红光,白光本身由等量的红光、绿光和蓝光组成。大多数在纸上沉积彩色颜料的设备,如彩色打印机和复印机,要求输入CMY数据或在内部进行RGB到CMY的转换。这一转换是使用下面这个简单的操作执行的:(假设所有的彩色值都归一化到了范围[0,1]内。

       但是我们为什么又需要用CMYK模型呢?等量的颜料原色(青色、深红色和黄色)可以生成黑色。实际上,C、M和Y油墨通常不是纯色的,组合这些颜色来印刷黑色时,反而会产生模糊的棕色。因此,为了生成真正的黑色(即在打印中起主要作用的颜色),加入了第4种颜色——黑色,提出了CMYK彩色模型。这样,当出版商提到“四色打印”时,指的就是CMY彩色模型的三种原色再加上部分黑色。

HSI(Hue、Saturation、intensity)彩色模型

       正如我们所见到的那样,在RGB模型和CMY模型中创建颜色并从一种模型转换到另一种模型是比较简单的过程。这些彩色系统对于硬件实现很理想。另外,RGB 系统与人眼强烈感知红、绿、蓝三原色的事实能很好地匹配。遗憾的是,RGB模型、CMY模型和其他类似的彩色模型不能很好地适应实际上人解释的颜色。例如,通过用给定的组成其颜色的每一原色的百分比不能给出一辆汽车的颜色,此外,我们不认为彩色图像是由3幅原色图像混合形成的单幅图像。
       当人观察一个彩色物体时,我们用其色调、饱和度和亮度来描述它。色调是描述一种纯色(纯黄色、纯橙色或纯红色)的颜色属性,然而,饱和度是一种纯色被白光稀释的程度的度量。亮度是一个主观的描述子,实际上它是不可度量的,它体现了无色的强度概念,并且是描述彩色感觉的关键因子之一。我们清楚地知道强度(灰度级)是单色图像最有用的描述子。很明确,这个量是可度量的,并很容易解释。
       我们即将提出的模型称为HSI(色调、饱和度和强度)彩色模型,该模型可在彩色图像中从携带的彩色信息(色调和饱和度)中消去强度分量的影响。因此,HSI模型是开发基于彩色描述的图像处理算法的理想工具,这种彩色描述对人来说是自然且直观的,毕竟人才是这些算法的开发者和使用者。HSI模型有独立控制色调、饱和度和强度的能力。
       HSI模型图示如下:


       有关更多的模型理解以及HSI模型和RGB模型之间的转换我们可以参考《数字图像处理》第四版,冈萨雷斯。

       opencv中有专门提供色彩转换的函数,这里无直接调用来进行转换,当然你也可以自己进行函数的编写完成这个任务。
有关cv2.cvtColor()函数的用法可以参考这里:cv2.cvtColor()函数

程序实现:

import cv2
import matplotlib.pyplot as plt

imgBGR = cv2.imread("China.jpg", flags = 1)  # flags=1 读取彩色图像(BGR)

plt.subplot(331), plt.title("BGR"), plt.axis('off')
plt.imshow(imgBGR)  # matplotlib显示BGR

plt.subplot(332), plt.title("RGB"), plt.axis('off')
imgRGB = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2RGB)  # BGR--->RGB
plt.imshow(imgRGB)  # matplotlib显示RGB

plt.subplot(333), plt.title("GRAY"), plt.axis('off')
imgGRAY = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2GRAY)  # BGR--->GRAY
plt.imshow(imgGRAY)  # matplotlib显示GRAY

plt.subplot(334), plt.title("HSV"), plt.axis('off')
imgHSV = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2HSV)  # BGR--->HSV
plt.imshow(imgHSV)  # matplotlib显示HSV

plt.subplot(335), plt.title("YCrCb"), plt.axis('off')
imgYCrCb = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2YCrCb)  # BGR--->YCrCb
plt.imshow(imgYCrCb)  # matplotlib显示YCrCb

plt.subplot(336), plt.title("HLS"), plt.axis('off')
imgHLS= cv2.cvtColor(imgBGR, cv2.COLOR_BGR2HLS)  # BGR--->HLS
plt.imshow(imgHLS)  # matplotlib显示HLS

plt.subplot(337), plt.title("XYZ"), plt.axis('off')
imgXYZ= cv2.cvtColor(imgBGR, cv2.COLOR_BGR2XYZ)  # BGR--->XYZ
plt.imshow(imgXYZ)  # matplotlib显示XYZ

plt.subplot(338), plt.title("LAB"), plt.axis('off')
imgLAB= cv2.cvtColor(imgBGR, cv2.COLOR_BGR2LAB)  # BGR--->LAB
plt.imshow(imgLAB)  # matplotlib显示LAB

plt.subplot(339), plt.title("YUV"), plt.axis('off')
imgYUV= cv2.cvtColor(imgBGR, cv2.COLOR_BGR2YUV)  # BGR--->YUV
plt.imshow(imgYUV)  # matplotlib显示YUV

plt.tight_layout() #自动调整子图间距
plt.show()

运行结果:

本文内容参考:
Opencv官网教程Changing Colorspaces
《数字图像处理》第四版—冈萨雷斯

本文代码已开源,欢迎大家进行二次开发:https://gitee.com/xiaolong_ROS/Graphics-Processing-and-Machine-Vision

如有错误或者不足之处,欢迎大家留言指正!

以上是关于常用彩色模型及转换的主要内容,如果未能解决你的问题,请参考以下文章

RGBCMYHSVHSL颜色空间

颜色的概念

使用OpenCV3处理图像

PS中的拾色器H 、S 、B 、是啥意思?

为什么要引入HSI彩色模型?

RGB颜色空间色调饱和度亮度HSV颜色空间详解