【OpenCV C++20 学习笔记】范围阈值操作
范围阈值操作
- 原理
- HSV颜色空间
- RGB与HSV颜色空间之间的转换
- 代码实现
- 颜色空间的转换
- 范围阈值操作
原理
HSV颜色空间
HSV(色相hue, 饱和度sarturation, 色明度value)颜色空间与RGB颜色空间相似。hue色相通道代表颜色类型;saturation饱和度通道代表颜色的饱和度,即颜色的浓淡或深浅、value通道代表颜色的亮度。下面的圆柱体展示了HSV颜色空间的模型:
RGB与HSV颜色空间之间的转换
RGB颜色空间是通过红、绿、蓝3种基本颜色的比例来确定颜色。RGB颜色空间模型如下:
OpenCV默认的是BGR颜色空间(相当于RGB),所以需要将RGB颜色空间转换成HSV颜色空间。在OpenCV中可以使用cv::cvtColor
函数来进行不同颜色空间之间的转换。每个通道之间的具体转换方法如下:
V ← m a x ( R , G , B ) V \leftarrow max(R,G,B) \\ V←max(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←{VV−min(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(G−B)/(V−min(R,G,B)120+60(B−R)/(V−min(R,G,B)240+60(R−G)/(V−min(R,G,)0ifV=RifV=GifV=BifR=G=B
- 如果计算出的 H < 0 H<0 H<0,则 H ← H + 360 H \leftarrow H+360 H←H+360;
- 计算出的H, S, V的范围分别是: 0 ≤ H ≤ 360 0 \leq H \leq 360 0≤H≤360, 0 ≤ S ≤ 1 0 \leq S \leq 1 0≤S≤1, 0 ≤ V ≤ 255 0 \leq V \leq 255 0≤V≤255
因为转换后的3个通道的颜色值可能会超出数据类型的最大值,所以还需要进行值域的转换
- 如果数据是8位: S ← 255 S , H ← H / 2 S \leftarrow 255S, H \leftarrow H/2 S←255S,H←H/2,即最终H, S, V的范围分别是: 0 ≤ H ≤ 180 0 \leq H \leq 180 0≤H≤180, 0 ≤ S ≤ 255 0 \leq S \leq 255 0≤S≤255, 0 ≤ V ≤ 255 0 \leq V \leq 255 0≤V≤255
- 如果数据是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 V←max(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 S←VV−min(R,G,B)=0
因为 R = G = B R = G = B R=G=B,所以有:
H ← 0 H \leftarrow 0 H←0
最后进行值域转换得:
S ← 255 S = 0 , H ← H / 2 = 127 S \leftarrow 255S = 0, H \leftarrow H/2 = 127 S←255S=0,H←H/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)0≤src(I)0≤upperb(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)0≤src(I)0≤upperb(I)0∧lowerb(I)1≤src(I)1≤upperb(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)0≤src(I)0≤upperb(I)0∧lowerb(I)1≤src(I)1≤upperb(I)1∧lowerb(I)2≤src(I)2≤upperb(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个物体被很好的识别出来了,但是另一个物体并没有,而且背景中的暗部也被识别了。
可以变换上下边界,查看不同的效果。
相关文章:

【OpenCV C++20 学习笔记】范围阈值操作
范围阈值操作 原理HSV颜色空间RGB与HSV颜色空间之间的转换 代码实现颜色空间的转换范围阈值操作 原理 HSV颜色空间 HSV(色相hue, 饱和度sarturation, 色明度value)颜色空间与RGB颜色空间相似。hue色相通道代表颜色类型;saturation饱和度通道代表颜色的饱和度&…...

【Material-UI】Checkbox组件:Indeterminate状态详解
文章目录 一、什么是Indeterminate状态?二、Indeterminate状态的实现1. 基本用法示例2. 代码解析3. Indeterminate状态的应用场景 三、Indeterminate状态的UI与可访问性1. 无障碍设计2. 用户体验优化 四、Indeterminate状态的最佳实践1. 状态同步2. 优化性能3. 提供…...

一文了解K8S(Kubernates)
一、K8S 1. 概述 Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。 Kubernetes 这个名字源于希腊…...

三星、小米和 OPPO设备实验室将采用Android设备流技术
早在 5 月份的年度开发者大会上,Google就发布了 Android 设备流测试版。开发人员可以在Google数据中心的真实物理设备上更轻松、更互动地测试自己的应用程序,这些设备会直接串流到 Android Studio。今天,Google宣布与三星、小米和 OPPO 合作扩…...
华为OD-D卷万能字符单词拼写
有一个字符串数组words和一个字符串chars。 假如可以用chars中的字母拼写出words中的某个“单词”(字符串),那么我们就认为你掌握了这个单词。 words的字符仅由 a-z 英文小写字母组成。 例如: abc chars 由 a-z 英文小写字母和 “?”组成。其…...

顶象文字点选模型识别
注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 文字点选如何训练,之前的文章说了很多遍了,这里只放现成的模型供查看,有需要成品联系…...

C#如何将自己封装的nuget包引入到项目中
问题 自己封装好了一个nuget包,但是不想上传到外网,想局域网使用,有两种方案 搭建私有nuget仓库放到离线文件夹中直接使用 第一种方式请请参考proget安装 下面主要是第二种方式 准备 新建类库项目 using System;namespace ClassLibrary…...
数据结构(学习)2024.8.8(栈,队列)
今天学习的是线性表里面的栈和队列 链表的相关知识可以查看http://t.csdnimg.cn/NX464 顺序表的相关知识可以查看http://t.csdnimg.cn/5IMAZ 目录 栈 栈的定义 栈的特点 顺序栈 结构体 顺序栈的相关操作案例 链式栈 结构体 链式栈的相关操作案例 总结 队列 队列…...
服务端开发常用知识(持续更新中)
Java方面 1 基础篇 1.1 网络基础 tcp三次握手和四次挥手-CSDN博客 tcp和udp区别,tcp拥塞控制算法和粘包问题-CSDN博客 http的发展历史,各版本的差异点,以及和https的区别-CSDN博客 2 jvm篇 3 多线程篇 4 mysql篇 5 redis篇 6 kafk…...
MySQL入门学习-运维与架构.复制过滤器
MySQL 复制过滤器是一种用于过滤复制数据的机制。它可以根据特定的规则,选择要复制的数据库、表或列,从而减少复制的数据量,提高复制性能。 一、以下是一些常见的 MySQL 复制过滤器: 1. 基于二进制日志的过滤器: 通过…...
【深度学习】生成领域里,Normalizing Flow、GAN、VAE、Diffusion Models的区别是什么?
文章目录 1. Normalizing Flow2. GAN (Generative Adversarial Networks)3. VAE (Variational Autoencoders)4. Diffusion Models总结1. Normalizing Flow公式代码示例2. GAN (Generative Adversarial Networks)公式代码示例3. VAE (Variational Autoencoders)公式代码示例4. D…...
Qt 串口通信(C++)
1. 基本概念 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接…...

聊聊AUTOSAR: 基于DaVinci的SecOC开发与配置
一、什么是SecOC 当前车载网络通讯环境越来越复杂,未采取任何安全保护的报文,一旦被伪造或者篡改,将非常危险。为了提升信息的安全性,AUTOSAR标准中引进了SecOC,加入了通讯认证机制,能够有效的辨别出信息是…...
.net6.0 重启控制台 命令
在.NET 6.0中,如果你想要创建一个命令行应用程序来重启当前运行的控制台,你可以使用System.Diagnostics命名空间下的Process类来启动一个新的进程,并结束当前进程。 以下是一个简单的示例代码,展示了如何实现重启控制台的功能&am…...

LVS 调度器 nat和DR模式
lvs-nat 修改请求报文的目标IP,多目标IP的DNAT 配置网络 LVS主机 注意网卡的顺序 (nat和主机模式) [rootlvs ~]# cat /etc/NetworkManager/system-connections/ens160.nmconnection [connection] idens160 typeethernet interface-nameens160 [ip…...

MTK Android12 SystemUI 手势导航 隐藏导航栏底部布局
问题:android12 平台手势导航情况下,app页面未设置全屏情况下,底部导航栏会有一个高度的颜色,底部导航会有一个手势导航提示条 需求:去掉手势导航情况下底部的导航栏和手势提示条 文章目录 相关资源修改问题描述解决方案代码跟踪中间提醒小方块代码查找底部手势导航条跟踪…...
electron调用c++ dll lib
主要的工具包 node-addon-apinode-gyp 主要的配置 {"variables": {# module_mac: "./../sdk/mac",},"targets": [{"target_name": "native_module","defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"],&qu…...
23种设计模式(持续更新中)
参考链接干货分享 | 《设计模式之美》学习笔记 - 知乎 (zhihu.com) 总体来说设计模式分为三大类: 创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共7种:适配器模式、…...

Linux文件系统详解
Linux的一切皆文件 Linux 中的各种事物比如像文档、目录(Mac OS X 和 Windows 系统下称之为文件夹)、键盘、监视器、硬盘、可移动媒体设备、打印机、调制解调器、虚拟终端,还有进程间通信(IPC)和网络通信等输入/输出资…...

大数据面试SQL(五):查询最近一笔有效订单
文章目录 查询最近一笔有效订单 一、题目 二、分析 三、SQL实战 四、样例数据参考 查询最近一笔有效订单 一、题目 现有订单表t5_order,包含订单ID,订单时间,下单用户,当前订单是否有效。 请查询出每笔订单的上一笔有效订…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...

【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...