当前位置: 首页 > news >正文

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

范围阈值操作

  • 原理
    • HSV颜色空间
    • RGB与HSV颜色空间之间的转换
  • 代码实现
    • 颜色空间的转换
    • 范围阈值操作

原理

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个物体被很好的识别出来了,但是另一个物体并没有,而且背景中的暗部也被识别了。
可以变换上下边界,查看不同的效果。

http://www.lryc.cn/news/418774.html

相关文章:

  • 【Material-UI】Checkbox组件:Indeterminate状态详解
  • 一文了解K8S(Kubernates)
  • 三星、小米和 OPPO设备实验室将采用Android设备流技术
  • 华为OD-D卷万能字符单词拼写
  • 顶象文字点选模型识别
  • C#如何将自己封装的nuget包引入到项目中
  • 数据结构(学习)2024.8.8(栈,队列)
  • 服务端开发常用知识(持续更新中)
  • MySQL入门学习-运维与架构.复制过滤器
  • 【深度学习】生成领域里,Normalizing Flow、GAN、VAE、Diffusion Models的区别是什么?
  • Qt 串口通信(C++)
  • 聊聊AUTOSAR: 基于DaVinci的SecOC开发与配置
  • .net6.0 重启控制台 命令
  • LVS 调度器 nat和DR模式
  • MTK Android12 SystemUI 手势导航 隐藏导航栏底部布局
  • electron调用c++ dll lib
  • 23种设计模式(持续更新中)
  • Linux文件系统详解
  • 大数据面试SQL(五):查询最近一笔有效订单
  • OpenCV图像滤波(8)getGaborKernel()函数的使用
  • 门店收银系统源码+同城即时零售多商户入驻商城源码
  • MaxKB:基于 LLM大语言模型的知识库问答系统实操
  • linux文件命令:更新文件时间戳的工具touch详解
  • Docker学习(6):Docker Compose部署案例
  • 4章3节:处理医学类原始数据的重要技巧,R语言中的宽长数据转换,tidyr包的使用指南
  • [Web安全架构] HTTP协议
  • mysql数据库之运算符
  • Spark轨迹大数据高效处理_计算两经纬度点间的距离_使用Haversine formula公式
  • [C++] : std::copy_n
  • centos上传工具