【OpenCV C++20 学习笔记】范围阈值操作

原理

HSV颜色空间

HSV(色相hue, 饱和度sarturation, 色明度value)颜色空间与RGB颜色空间相似。hue色相通道代表颜色类型;saturation饱和度通道代表颜色的饱和度,即颜色的浓淡或深浅、value通道代表颜色的亮度。下面的圆柱体展示了HSV颜色空间的模型:
HSV颜色空间模型

RGB与HSV颜色空间之间的转换

RGB颜色空间是通过红、绿、蓝3种基本颜色的比例来确定颜色。RGB颜色空间模型如下:

RGB颜色空间模型

OpenCV默认的是BGR颜色空间(相当于RGB),所以需要将RGB颜色空间转换成HSV颜色空间。在OpenCV中可以使用cv::cvtColor函数来进行不同颜色空间之间的转换。每个通道之间的具体转换方法如下:
V ← m a x ( R , G , B ) V \leftarrow max(R,G,B) \\ Vmax(R,G,B)
S ← { V − m i n ( R , G , B ) V if V ≠ 0 0 otherwise S \leftarrow \begin{cases} \frac{V-min(R,G,B)}{V} & \text{if} \quad V \neq 0 \\ 0 & \text{otherwise} \end{cases} \\ S{VVmin(R,G,B)0ifV=0otherwise
H ← { 60 ( G − B ) / ( V − m i n ( R , G , B ) if V = R 120 + 60 ( B − R ) / ( V − m i n ( R , G , B ) if V = G 240 + 60 ( R − G ) / ( V − m i n ( R , G , ) if V = B 0 if R = G = B H \leftarrow \begin{cases} 60(G-B)/(V-min(R,G,B) & \text{if} \quad V=R \\ 120+60(B-R)/(V-min(R,G,B) & \text{if} \quad V=G \\ 240+60(R-G)/(V-min(R,G,) & \text{if} \quad V=B \\ 0 & \text{if} \quad R=G=B \end{cases} H 60(GB)/(Vmin(R,G,B)120+60(BR)/(Vmin(R,G,B)240+60(RG)/(Vmin(R,G,)0ifV=RifV=GifV=BifR=G=B

  • 如果计算出的 H < 0 H<0 H<0,则 H ← H + 360 H \leftarrow H+360 HH+360
  • 计算出的H, S, V的范围分别是: 0 ≤ H ≤ 360 0 \leq H \leq 360 0H360, 0 ≤ S ≤ 1 0 \leq S \leq 1 0S1, 0 ≤ V ≤ 255 0 \leq V \leq 255 0V255

因为转换后的3个通道的颜色值可能会超出数据类型的最大值,所以还需要进行值域的转换

  • 如果数据是8位: S ← 255 S , H ← H / 2 S \leftarrow 255S, H \leftarrow H/2 S255S,HH/2,即最终H, S, V的范围分别是: 0 ≤ H ≤ 180 0 \leq H \leq 180 0H180, 0 ≤ S ≤ 255 0 \leq S \leq 255 0S255, 0 ≤ V ≤ 255 0 \leq V \leq 255 0V255
  • 如果数据是16位:目前还不支持
  • 如果数据是32位:不需要转换

用RGB中的白色来举例。在8位的RGB颜色中,3个通道分别是 R = 255 R=255 R=255 G = 255 G=255 G=255 B = 255 B=255 B=255。根据上面的转换公式,转换成HSV颜色空间,则有:
V ← m a x ( R , G , B ) = 255 V \leftarrow max(R, G, B) = 255 Vmax(R,G,B)=255
V ≠ 0 V \neq 0 V=0,所以有:
S ← V − m i n ( R , G , B ) V = 0 S \leftarrow \frac{V-min(R,G,B)}{V} = 0 SVVmin(R,G,B)=0
因为 R = G = B R = G = B R=G=B,所以有:
H ← 0 H \leftarrow 0 H0
最后进行值域转换得:
S ← 255 S = 0 , H ← H / 2 = 127 S \leftarrow 255S = 0, H \leftarrow H/2 = 127 S255S=0,HH/2=127
所以, R G B ( 255 , 255 , 255 ) RGB(255, 255, 255) RGB(255,255,255)转换成 H S V 为: HSV为: HSV为:HSV(0, 0, 127)$。
下面将展示一个用HSV颜色空间来分离图片中的对象的例子:

代码实现

这里使用的图片是来自下载的OpenCV中自带的示例图片:...\opencv\sources\samples\data\stuff.jpg。原图如下:
示例原图
将该图片导入为src:

Mat src{ imread("stuff.jpg") };

颜色空间的转换

由于导入的图片默认是BGR模式,所以要使用cv::cvtColor函数进行颜色空间的转换:

Mat src_HSV;
cvtColor(src,		//原图
	src_HSV,		//结果图
	COLOR_BGR2HSV);	//颜色空间转换类型:BGR转为HSV

转换后的效果如下:
颜色空间转换结果

范围阈值操作

范围阈值操作由inRange()函数完成,其函数原型如下:

void cv::inRange(InputArray	src,
				InputArray	lowerb,
				InputArray	upperb,
				OutputArray	dst)
  • src:原图
  • lowerb:数组或Scalar类型,表示范围的最小边界
  • upperb:数组或Scalar类型,表示范围的最大边界
  • dst:输出图(与原图尺寸相同,CV_8U类型)

这个函数检查图片中的每个值,看它们是否落在其定义的范围内。其检查方法具体如下:

  • 对于单通道图片
    d s t ( I ) = l o w e r b ( I ) 0 ≤ s r c ( I ) 0 ≤ u p p e r b ( I ) 0 dst(I)=lowerb(I)_0 \leq src(I)_0 \leq upperb(I)_0 dst(I)=lowerb(I)0src(I)0upperb(I)0
  • 对于双通道图片:
    d s t ( I ) = l o w e r b ( I ) 0 ≤ s r c ( I ) 0 ≤ u p p e r b ( I ) 0 ∧ l o w e r b ( I ) 1 ≤ s r c ( I ) 1 ≤ u p p e r b ( I ) 1 dst(I)=lowerb(I)_0 \leq src(I)_0 \leq upperb(I)_0 \land lowerb(I)_1 \leq src(I)_1 \leq upperb(I)_1 dst(I)=lowerb(I)0src(I)0upperb(I)0lowerb(I)1src(I)1upperb(I)1
  • 对于3通道图片:由上类推
    d s t ( I ) = l o w e r b ( I ) 0 ≤ s r c ( I ) 0 ≤ u p p e r b ( I ) 0 ∧ l o w e r b ( I ) 1 ≤ s r c ( I ) 1 ≤ u p p e r b ( I ) 1 ∧ l o w e r b ( I ) 2 ≤ s r c ( I ) 2 ≤ u p p e r b ( I ) 2 dst(I)=lowerb(I)_0 \leq src(I)_0 \leq upperb(I)_0 \land \\ \qquad lowerb(I)_1 \leq src(I)_1 \leq upperb(I)_1 \land \\ \qquad lowerb(I)_2 \leq src(I)_2 \leq upperb(I)_2 dst(I)=lowerb(I)0src(I)0upperb(I)0lowerb(I)1src(I)1upperb(I)1lowerb(I)2src(I)2upperb(I)2
    所以,无论是多少通道的图片,指定的范围都是一个闭区间。如果图片中的某个值低于范围的下边界,那就会被赋予下边界值;同理,如果超过上边界,就会被赋予上边界的值。
    当上下边界是用Scalar类型定义的时候,上面几个公式就不用加小括号来表示数组的下标了。
    注意,转换成HSV格式之后,颜色值的最大值变成了Scalar(180, 255, 255).
    本例中使用最大值为上边界,最大值的1/6为下边界:
Mat dst;
inRange(src_HSV,			//HSV图
	Scalar(30, 37, 37),		//下边界
	Scalar(180, 255, 255),	//上边界
	dst);					//输出图

最终效果如下:
范围阈值操作效果
可以看到3个物体被很好的识别出来了,但是另一个物体并没有,而且背景中的暗部也被识别了。
可以变换上下边界,查看不同的效果。

  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值