本文主要是介绍【ISP】HSV(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
之前听别人总说,HSV的颜色空间更符合人类对颜色的理解,我一直不明白是什么意思。最近做了相关项目,对HSV有了一定的理解。
我现在问你一个简单的问题,假设有一幅图像,如下图所示,请问怎么找出如下蓝色区域呢?
如果你从RGB去考虑,发现R、G、B三个通道的阈值不是很好调整,并不直观,那么我们从HSV的角度呢,请从下面的HSV颜色图谱种进行比对寻找。
是不是有了思路,H在200到260左右,S在0.2到1之间,V大约在0.3到1之间,你估计出的值可能和我的有一点点不同,但总体范围应该是相似的,从这里你们发现没,我居然很轻松的就定义了蓝色的大致范围,很好的就能找到蓝色的区域。
原理解析及伪代码
1.HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、亮度(Value)。
色调(H):用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度(S)表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
亮度(V)表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。HSV颜色空间可以用一个圆锥空间模型来描述。圆锥的顶点处,V=0,H和S无定义,代表黑色。圆锥的顶面中心处V=max,S=0,H无定义,代表白色。
2. RGB和HSV转换
(1) 从RGB到HSV
max=max(R,G,B);
min=min(R,G,B);
V=max(R,G,B);
S=(max-min)/max;
if (R = max) H =(G-B)/(max-min)* 60;
if (G = max) H = 120+(B-R)/(max-min)* 60;
if (B = max) H = 240 +(R-G)/(max-min)* 60;
if (H < 0) H = H+ 360;
(2)从HSV到RGB
if (s = 0)
R=G=B=V;
else
H /= 60;
i = INTEGER(H);
f = H - i;
a = V * ( 1 - s );
b = V * ( 1 - s * f );
c = V * ( 1 - s * (1 - f ) );
switch(i)
case 0: R = V; G = c; B = a;
case 1: R = b; G = v; B = a;
case 2: R = a; G = v; B = c;
case 3: R = a; G = b; B = v;
case 4: R = c; G = a; B = v;
case 5: R = v; G = a; B = b;
HSV对用户来说是一种直观的颜色模型。我们可以从一种纯色彩开始,即指定色彩角H,并让V=S=1,然后我们可以通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=240度。要得到淡蓝色,V=1 S=0.4 H=240度。
Python-Opencv
颜色空间转换
- RGB就是指Red,Green和Blue,一副图像由这三个channel(通道)构成
- Gray就是只有灰度值一个channel
- HSV即Hue(色调),Saturation(饱和度)和Value(亮度)三个channel
RGB是为了让机器更好的显示图像,对于人类来说并不直观,HSV更为贴近我们的认知,所以通常我们在针对某种颜色做提取时会转换到HSV颜色空间里面来处理。
利用opencv把RGB图片像HSV颜色空间转变的时候,
H通道的值范围为:
0-180
S: 0-255
V:0-255
利用直方图显示三个通道的时候,H通道都集中在前半部分,想让它取值范围扩大~~~~~~~
后来发现了 CV_BGR2HSV_FULL ,
CV_BGR2HSV 在转换图像的时候是将 H / 2 ---> H ,我们知道图像中色相H的取值范围为 0-360 ,所以利用opencv转换之后得到的H的范围为 0-180
而 CV_BGR2HSV_FULL 实现的映射是 H * 255 / 360 --->H , 所以利用_FULL 这个转换得到的H通道图像的范围为 0-255
这两种方式都是opencv把[0-360] 的数据压缩到一个字节可以处理的数据。[ 所以这里说的图像的depth = 8, 刚好能表示的最大值是 255]
上面说的图像的 depth = 8, 如果你的图像 位深不是 8位,比如 32 位, 那么你就可以得到 [0, 360] 表示的 H通道图像了。
所以,总结如下:
HSV颜色模型规定的各通道取值范围为: H :0-360 S:0-1 V: 0-1
可以利用 CV_BGR2HSV 得到的对应的HSV: H: 0-180 S:0-255 V:0-255
例子
提取蓝色物体
Img = cv2.imread(Imgpath)
HSV = cv2.cvtColor(Img, cv2.COLOR_BGR2HSV)
H, S, V = cv2.split(HSV)
LowerBlue = np.array([100, 100, 50])
UpperBlue = np.array([130, 255, 255])
mask = cv2.inRange(HSV, LowerBlue, UpperBlue)
BlueThings = cv2.bitwise_and(Img, Img, mask=mask)
PS:
RGB在OpenCV中存储为BGR的顺序,数据结构为一个3D的numpy.array,索引的顺序是行,列,通道:
BGRImg = cv2.imread(ImgPath)
B = BGRImg[:, :, 0]
G = BGRImg[:, :, 1]
R = BGRImg[:, :, 2]
也可以使用:
BGRImg = cv2.imread(ImgPath)
B, G, R = cv2.split(BGRImg)
注意,cv2.split的速度比直接索引要慢,但cv2.split返回的是拷贝,直接索引返回的是引用(改变B就会改变BGRImg)
TIPS:本文所有代码均在/Src/ImageProcessing/ColorSpace/ColorSpaces.py
这篇关于【ISP】HSV(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!