第三章-OpenCV基础-5-色彩处理

前置内容 

RGB色彩空间是常见的色彩的空间,其他还有GRAY色彩空间、HSV色彩空间等等,它们都可以从不同的角度进行理解颜色。

类比于数字10,它可以表示为二进制、八进制或者十六进制,以不同的规则来表示,都没有错误,但各个进制的计算必须按照各个进制的规则来执行,

色彩空间同样如此,各个色彩空间之间可以相互转换,类比不同进制之间也可以进行转换。

色彩空间基础

GRAY色彩空间

当图像从RGB色彩空间转变为GRAY色彩空间(灰度图)时,标准转换公式为: GRAY=0.299 * R + 0.587 * G + 0.114 * B

有时也可以简化计算转换: GRAY = ( R + G + B ) / 3

当GRAY色彩空间转换为BGR色彩空间时,所有通道将是一样的: B = G = R = GRAY

HSV色彩空间

RGB通过三种基色的不同比例混合成各种颜色,而在实际更习惯用直观的方式来感知颜色,这就是HSV色彩空间。

HSV色彩空间包含色调H、饱和度S、明度V

  • 色调H(Hue)

色调即光的颜色。我们知道,阳光是混合光,中间包含赤橙黄绿青蓝紫等各种光,这些不同颜色的光因为光波波长的不一样表现为不同的颜色,这些不同的光即是不同的色调。

在HSV色彩空间中,色调H的取值范围为[0,360],而每个像素点的取值范围为[0.255],为了把色调在[0,360]映射到[0,255]中,OpenCV将色调除以2,得到的值为[0,180],以适应8位2进制数的存储和表示范围。

部分典型颜色对应的值如下:

颜色

色调

OpenCV内的值

红色

0

0

黄色

60

30

绿色

120

60

青色

180

90

蓝色

240

120

品红

300

150

色调使用简单说明:在HSV图像中,H通道120的值对应的像素点是蓝色的。

  • 饱和度S(Saturation)

饱和度是指色彩的鲜艳程度,表示为色彩的相对纯净度。饱和度取决于色彩中灰色的占比,灰色越多,色彩饱和度越低。当色彩不包含灰色,此时色彩表现为纯色。

当颜色的饱和度很低时(灰色太多了),计算的色调(光色)就不准确了,此时没有彩色信息只有灰色信息了。

饱和度取值范围为[0,1],饱和度为0时,只有灰度,饱和度为1时,此时为纯色。

为了在8位位图中显示,饱和度也需要将[0,1]映射到[0,255]。

  • 明度V(Value)

明度指人眼感受到的色彩明亮程度,反映的是人眼感受到的光的明暗程度。

对于无彩色(黑、白、灰),白色的明度最高,黑色的明度最低,白色和黑色之间存在不同明度的灰色。

对于彩色图像来说,明度越高,图像越光亮,反之越暗淡。

明度的取值范围为[0,1],在OpenCV中也要映射到[0,255]上。

举例说明:

色调=0 饱和度=1 明度=1,人眼看到的色彩为红色,且颜色较亮。

色调=120 饱和度=0.3 明度=0.4,人眼看到的色彩为浅绿色,且颜色较暗。

色彩空间转换

OpenCV提供了方法实现不同色彩空间的转换

dst = cv2.cvtColor( src , code [,dstCn] )

dst : 转换后的输出图像,与原图具有相同的数据类型和深度。

src : 原始输入图像

code : 色彩空间转换码,此参数告诉OpenCV要从哪个色彩空间转换到哪个色彩空间,具体长的是cv2.COLOR_XXX2YYY

dstCn : 目标图像的通道数

各空间转换过程中不可避免存在映射操作造成的四舍五入情况,故来回转换色彩空间过程不是精准可逆。

举例-提取肤色

根据肤色在HSV色彩空间的范围可以将包含肤色的部分提取出来

  • 色调值[0,33]
  • 饱和度[10,255]
  • 明度值[80,255]

具体实现如下:

import cv2 as cv
import numpy as np

img = cv.imread("x.png")
# BGR转为HSV
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
print(hsv)  # HSV色彩空间的数据 二维数组的[H S V]或者三维数组
min_HSV = np.array([0, 10, 80], dtype="uint8")  # [0 10 80]
max_HSV = np.array([33, 255, 255], dtype="uint8")  # [33 255 255]
# cv2.inRange(src,min,max)低于min或高于max的值置为0 在min和max范围内的值置为255
mask = cv.inRange(hsv, min_HSV, max_HSV)
print(mask)  # 掩模嘛,就是个二维数组
result = cv.bitwise_and(img, img, mask=mask)  # 2个img这个我看的有点懵一开始,自己与自己,等于自己,就是图像在掩模作用范围内做算法
cv.imshow("img", img)
cv.imshow("mask", mask)
cv.imshow("result", result)
cv.waitKey()
cv.destroyAllWindows()

运行如下(本来想用lena的色彩图,但整张lena图对黄色比较广且杂,效果不大好):

猜你喜欢

转载自blog.csdn.net/sunguanyong/article/details/129232791