1. 颜色空间转换
- RGB(地球人都知道)
RGB 是我们接触最多的颜色空间,由三个通道表示一幅图像,分别为红色(R),绿色(G)和蓝色(B)。这三种颜色的不同组合可以形成几乎所有的其他颜色。自然环境下获取的图像容易受自然光照、遮挡和阴影等情况的影响,即对亮度比较敏感。而 RGB 颜色空间的三个分量都与亮度密切相关,即只要亮度改变,三个分量都会随之相应地改变,而没有一种更直观的方式来表达。但是人眼对于这三种颜色分量的敏感程度是不一样的,在单色中,人眼对红色最不敏感,蓝色最敏感,所以 RGB 颜色空间是一种均匀性较差的颜色空间。如果颜色的相似性直接用欧氏距离来度量,其结果与人眼视觉会有较大的偏差。对于某一种颜色,我们很难推测出较为精确的三个分量数值来表示。所以,RGB 颜色空间适合于显示系统,却并不适合于图像处理
2. HSV
基于上述理由,在图像处理中使用较多的是 HSV 颜色空间,它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比。在 HSV 颜色空间下,比 BGR 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。HSV中只有Hue一个通道表示颜色。
HSV 表达彩色图像的方式由三个部分组成:
- Hue(色调、色相)
- Saturation(饱和度、色彩纯净度):饱和度表示颜色接近光谱色的程度。饱和度越高,说明颜色越深,越接近光谱色饱和度越低,说明颜色越浅,越接近白色。饱和度为0表示纯白色。取值范围为0~100%,值越大,颜色越饱和。
- Value(明度):决定颜色空间中颜色的明暗程度,明度越高,表示颜色越明亮,范围是 0-100%。明度为0表示纯黑色(此时颜色最暗)
- HSV的取值范围:原本输出的 HSV 的取值范围分别是 0-360, 0-1, 0-1;但是为了匹配目标数据类型 OpenCV 将每个通道的取值范围都做了修改,于是就变成了 0-180, 0-255, 0-255,并且同时解释道:为了适应 8bit 0-255 的取值范围,将 hue 通道 0-360 的取值范围做了减半处理,这就是为什么 OpenCV 中 hue 通道的取值范围是0-180;
如何理解:
在Hue一定的情况下,饱和度减小,就是往光谱色中添加白色,光谱色所占的比例也在减小,饱和度减为0,表示光谱色所占的比例为零,导致整个颜色呈现白色。明度减小,就是往光谱色中添加黑色,光谱色所占的比例也在减小,明度减为0,表示光谱色所占的比例为零,导致整个颜色呈现黑色。
HSV 对用户来说是一种比较直观的颜色模型。我们可以很轻松地得到单一颜色,即指定颜色角H,并让V=S=1,然后通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=240度。要得到浅蓝色,V=1 S=0.4 H=240度。
RGB颜色空间更加面向于工业,而HSV更加面向于用户,大多数做图像识别这一块的都会运用HSV颜色空间,因为HSV颜色空间表达起来更加直观!
3. HLS
HSI色彩空间是从人的视觉系统出发,用色调(Hue)、色饱和度(Saturation 或Chroma)和亮度 (Intensity或Brightness)来描述色彩。HSI色彩空间可以用一个圆锥空间模型来描述。用这种 描述HIS色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度的变化情形表现得很清楚。 通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度。由于人的视觉对亮度的敏感 程度远强于对颜色浓淡的敏感程度,为了便于色彩处理和识别,人的视觉系统经常采用HSI色彩空间, 它比RGB色彩空间更符合人的视觉特性。在图像处理和计算机视觉中大量算法都可在HSI色彩空间中 方便地使用,它们可以分开处理而且是相互独立的。因此,在HSI色彩空间可以大大简化图像分析 和处理的工作量。HSI色彩空间和RGB色彩空间只是同一物理量的不同表示法,因而它们之间存在着 转换关系.HSL(色相hue, 饱和度saturation, 亮度lightness/luminance),也称HLS 或 HSI (I指intensity) 与HSV非常相似,仅用亮度(lightness)替代了明度(brightness).
二者区别在于,一种纯色的明度等于白色的明度,而纯色的亮度等于中度灰的亮度。(没看懂说啦个啥)
HLS 中的 L 分量为亮度,亮度为100,表示白色,亮度为0,表示黑色;HSV 中的 V 分量为明度,明度为100,表示光谱色,明度为0,表示黑色。提取白色物体时,使用 HLS 更方便,因为 HSV 中的Hue里没有白色,白色需要由S和V共同决定(S=0, V=100)。而在 HLS 中,白色仅由亮度L一个分量决定。所以检测白色时使用 HSL 颜色空间更准确。
参考链接:
- https://zhuanlan.zhihu.com/p/67930839
- https://blog.csdn.net/taily_duan/article/details/51506776
转换代码如下:
def color_space_demo(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)cv.imshow("gray", gray)hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)cv.imshow("hsv", hsv)hls = cv.cvtColor(image, cv.COLOR_BGR2HLS)cv.imshow("hls", hls)yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV) #下面俩个没看cv.imshow("yuv", yuv)ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)cv.imshow("ycrcb", ycrcb)
2. 将某种颜色的物体提取出来-cv2.inRange()
cv2.inRange(hsv, lower_red, upper_red):函数很简单,参数有三个:
- hsv指的是原图
- lower_red指的是图像中低于这个lower_red的值,图像值变为0
- upper_red指的是图像中高于这个upper_red的值,图像值变为0而在lower_red~upper_red之间的值变成255
- 最后输出的图像是二值图。、
HSV中H、S、V对照表:
代码如下:
def extract_object_demo(): #将某种颜色的对象显示出来capture = cv.VideoCapture("../images/cv.gif")while True:ret, frame = capture.read()if ret is False: # 如果没有获取到视频帧则返回falsebreakhsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)lower_hsv = np.array([0, 43, 46]) # hsv中h,s,v的最小值upper_hsv = np.array([50, 255, 255]) # hsv中的h,s,v最大值# 提取指定范围颜色,保留指定范围颜色, 其余置为黑(0)mask = cv.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv) # 用inRange函数提取指定颜色范围,这里对hsv来处理dst = cv.bitwise_and(frame, frame, mask = mask)cv.imshow("video", frame)cv.imshow("mask", mask)cv.imshow("mask1", dst)c = cv.waitKey(40)if c == 27:break
3. 通道的分离和合并-cv2.split()、cv2.merge()
- cv2.split():一个参数:np.ndarray格式的数据
- cv2.merge() :将各个通道的值以列表的形式表示出来,不能合并多个多通道的图像。
代码如下:
def channels_split_merge(image):b, g, r = cv.split(image) # b通道提取时,对该通道颜色保留,其余通道置为0cv.imshow("blue", b)cv.imshow("green", g)cv.imshow("red", r)changed_image = image.copy()changed_image[:, :, 2] = 0 # 将r通道颜色全部置为0cv.imshow("changed_image", changed_image)merge_image = cv.merge([b, g, r])cv.imshow("merge_image", merge_image)