Opencv+ROS实现颜色识别应用
目录
一、工具
二、原理
概念
本质
三、实践
添加发布话题
主要代码
四、成果
五、总结
一、工具
opencv+ros
ubuntu18.04
摄像头
二、原理
概念
彩色图像:RGB(红,绿,蓝)
HSV图像:H(色调)S(饱和度)V(亮度)
色调(H:hue):用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度(S:saturation):取值范围为0.0~1.0,值越大,颜色越饱和。
亮度(V:value):取值范围为0(黑色)~255(白色)。
但是在opencv中引用的范围有所不同,给出下表。
本质
颜色识别本质就是在图像上提取出你想要的颜色阈值,然后通过降噪优化模型,轮廓检测进行框选。
要点:
- RGB转HSV
- 所需颜色阈值(hsv),并二值化
- 腐蚀操作除噪,Canny算法进行边缘检测
- 最后通过findContours()函数找出轮廓坐标
三、实践
读取摄像头
VideoCapture cap(video_device); //dev/video0
RGB转HSV
cvtColor(frame, imghsv, COLOR_BGR2HSV);
直方图均衡化
split(imghsv, hsvSplit);
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, imghsv);
直方图均衡化是一种简单有效的图像增强技术,用于增强动态范围偏小的图像的对比度
定义颜色阈值,这里选取红色
Scalar lower_red(156, 43, 46);Scalar upper_red(180, 255, 255); // 定义红色的HSV范围inRange(imghsv, lower_red, upper_red, mask);//二值化红色部分
inRange()函数就是检测imghsv内所有像素是否在lower-upper之间,如果是则设为255,也就是白色。输出的是二值图。
用腐蚀,膨胀操作去噪点
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));morphologyEx(mask, mask, MORPH_OPEN, kernel);//开运算morphologyEx(mask, mask, MORPH_CLOSE, kernel);//闭运算
腐蚀,膨胀操作的对象是二值化图像
- 腐蚀:变精细
- 膨胀:变粗矿
- 开运算:先腐蚀后膨胀 消去一个黑图中的很多小白点
- 闭运算:先膨胀后腐蚀 消去一个白图中的很多小黑点
- 梯度运算:膨胀-腐蚀
高斯滤波,Canny边缘检测
GaussianBlur(mask, mask, Size(3, 3), 0);//高斯滤波Canny(mask, mask, 100, 250);//canny算子边缘检测
Canny()函数参数表明:
第一个:InputArray类型的image,输入图像
第二个:OutputArray类型的edges,输出的边缘图
第三个:double类型的threshold1,第一个滞后性阈值
第四个:double类型的threshold2,第二个滞后性阈值
Canny过程为
- 高斯滤波获得平滑图像
- 计算每个像素点的梯度强度和方向
- 应用非极大值抑制,消除边缘检测带来的杂散响应
- 双阈值确定真实或潜在的边缘
- 抑制弱化边缘完成边缘检测
然后开始找轮廓
findContours()函数
findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE,Point());
第一个参数:输入图像
第二个参数:所有轮廓
第三个参数:表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
第四个参数:RETR_EXTERNAL只检测最外围轮廓
第五个参数:CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息
寻找最大轮廓
vector<double> Area(contours.size());//寻找最大面积的轮廓for (int i = 1; i < contours.size(); i++) {Area[i] = contourArea(contours[i]);if (Area[i] > Area[max]) {max = i;} }Rect boundRect = boundingRect(Mat(contours[max]));circle(frame, Point(boundRect.x + boundRect.width/2, boundRect.y + boundRect.height/2), 5, Scalar(0,0,255), -1);
boundingRect()函数
表示包围轮廓的最大矩形
返回四个参数
第一个:boundRect.x
第二个:boundRect.y
第三个:boundRect.width
第四个:boundRect.hight
左上角顶点的像素坐标值及矩形边界的宽和高
然后将矩形在原画面画出即可
ROS_INFO("x:%d,y:%d",boundRect.x+ boundRect.width/2, boundRect.y + boundRect.height/2);
rectangle(frame, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar( 0, 0, 255), 2);
添加发布话题
毕竟是在ros下编写的,我们要把像素坐标发布出去,这里自定义一个消息类型
boundingbox.msg
用来表示类和坐标值
主要代码
while (ros::ok()) { cap >> frame; //摄像头画面赋给frameif(!frame.empty()) //画面是否正常{ /*对图片二次处理*/cvtColor(frame, imghsv, COLOR_BGR2HSV);// 将图像转换为HSV颜色空间split(imghsv, hsvSplit);equalizeHist(hsvSplit[2], hsvSplit[2]);merge(hsvSplit, imghsv);inRange(imghsv, lower_red, upper_red, mask);//二值化红色部分Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));morphologyEx(mask, mask, MORPH_OPEN, kernel);//开运算morphologyEx(mask, mask, MORPH_CLOSE, kernel);//闭运算GaussianBlur(mask, mask, Size(5, 5), 0);//高斯滤波Canny(mask, mask, 150, 100);//canny算子边缘检测vector<vector<Point> > contours;vector<Vec4i> hierarchy;findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE,Point()); //ROS_INFO("个数为%d",int(contours.size()));vector<double> Area(contours.size());if(contours.size() > 0 ){//寻找最大面积的轮廓for (int i = 1; i < contours.size(); i++) {Area[i] = contourArea(contours[i]);if (Area[i] > Area[max]) {max = i;} }Rect boundRect = boundingRect(Mat(contours[max]));circle(frame, Point(boundRect.x + boundRect.width/2, boundRect.y + boundRect.height/2), 5, Scalar(0,0,255), -1);ROS_INFO("x:%d,y:%d",boundRect.x+ boundRect.width/2, boundRect.y + boundRect.height/2);rectangle(frame, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar( 0, 0, 255), 2);detect_msg.Class = "red";detect_msg.xmin = boundRect.x;detect_msg.xmax=boundRect.x + boundRect.width;detect_msg.ymin=boundRect.y;detect_msg.ymax= boundRect.y + boundRect.height;}
四、成果
运行画面
查看话题
这里识别画面内所有红色区域
五、总结
写代码过程中还是遇到很多问题的,不知道是opencv版本不兼容的问题还是哪里我编写不细致,节点总是挂掉。
但还是能完成基本需求。
这里把报错留下,希望有大佬能帮帮我
OpenCV Error: Assertion failed (npoints >= 0 && (depth == CV_32F || depth == CV_32S)) in pointSetBoundingRect, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/shapedescr.cpp, line 466
terminate called after throwing an instance of 'cv::Exception'
what(): /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/shapedescr.cpp:466: error: (-215) npoints >= 0 && (depth == CV_32F || depth == CV_32S) in function pointSetBoundingRect
应该是boundingRect()函数的问题,但不知道问题在哪
欢迎评论区指正。
相关文章:

Opencv+ROS实现颜色识别应用
目录 一、工具 二、原理 概念 本质 三、实践 添加发布话题 主要代码 四、成果 五、总结 一、工具 opencvros ubuntu18.04 摄像头 二、原理 概念 彩色图像:RGB(红,绿,蓝) HSV图像:H࿰…...
蓝桥杯c++算法秒杀【6】之动态规划【下】(数字三角形、砝码称重(背包问题)、括号序列、异或三角:::非常典型的必刷例题!!!)
别忘了请点个赞收藏关注支持一下博主喵!!!! ! ! ! ! 关注博主,更多蓝桥杯nice题目静待更新:) 动态规划 三、括号序列 【问题描述】 给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合…...

C++设计模式(单例模式)
一、介绍 1.动机 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例? 这应该是类设计者的…...

前端---CSS(部分用法)
HTML画页面--》这个页面就是页面上需要的元素罗列起来,但是页面效果很差,不好看,为了让页面好看,为了修饰页面---》CSS CSS的作用:修饰HTML页面 用了CSS之后,样式和元素本身做到了分离的效果。---》降低了代…...

2024年最新版Java八股文复习
最新版本Java八股文复习,每天更新一篇,博主正在持续努力更新中~~~ 一、Java基础篇1、怎么理解面向对象?简单说说封装、继承、多态三大特性?2、多态体现在哪几个方面?3、面向对象的设计原则你知道有哪些吗?4…...

计算机毕业设计Hadoop+Spark音乐推荐系统 音乐预测系统 音乐可视化大屏 音乐爬虫 HDFS hive数据仓库 机器学习 深度学习 大数据毕业设计
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

MyBatis高级扩展
一、Mapper批量映射优化: 1.需求: Mapper 配置文件很多时,在全局配置文件中一个一个注册太麻烦,希望有一个办法能够一劳永逸 2.配置方式: Mybatis允许在指定Mapper映射文件时,只指定其所在的包: <mappers><package name"c…...

代码美学2:MATLAB制作渐变色
效果: %代码美学:MATLAB制作渐变色 % 创建一个10x10的矩阵来表示热力图的数据 data reshape(1:100, [10, 10]);% 创建热力图 figure; imagesc(data);% 设置颜色映射为“cool” colormap(cool);% 在热力图上添加边框 axis on; grid on;% 设置热力图的颜色…...

浅谈- “ 变量中 无符号 与 有符号 的 值转换 ”
在同一个表达式中,若同时出现 无符号变量 与 有符号变量 : 1、都转换为无符号类型:(注:2^324294967296)即unsigned int 的最大值 2、然后再运行表达式 实例: #include <stdio.h>char fun(…...

【AI绘画】Midjourney进阶:色调详解(上)
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 💯前言💯Midjourney中的色彩控制为什么要控制色彩?为什么要在Midjourney中控制色彩? 💯色调白色调淡色调明色调 💯…...

代码管理之Gitlab
文章目录 Git基础概述场景本地修改未提交,拉取远程代码修改提交本地,远程已有新提交 GitIDEA引入Git拉取仓库代码最后位置 Git基础 概述 workspace 工作区:本地电脑上看到的目录; repository 本地仓库:就是工作区中隐…...

防御网络攻击的创新策略
关键要点 ● 了解各种类型的网络攻击对于组织加强防御至关重要。 ● 制定敏捷的网络安全策略可帮助企业快速应对新出现的威胁。 ● 跨行业协作和威胁情报共享可以增强整体安全性。 网络攻击威胁日益严重 网络攻击的数量和复杂程度急剧增加,对全球组织构成了重大…...
C++软件设计模式之组合模式概述
组合模式(Composite Pattern)是C软件设计模式中的一种,主要用于解决对象的层次结构问题。它允许你将对象组合成树形结构来表示“部分-整体”的层次结构,使得客户端可以统一地处理单个对象和组合对象。 主要用于解决的问题&#x…...
利用HTML5和CSS来实现一个漂亮的表格样式
利用HTML5和CSS来实现一个漂亮的表格样式 第一步:创建HTML结构第二步:添加CSS样式第三步:响应式设计第四步:加入交互效果 第一步:创建HTML结构 我们将用HTML创建一个基本的表格结构。代码如下: <!DOCT…...

Vivado程序固化到Flash
在上板调试FPGA时,通常使用JTAG接口下载程序到FPGA芯片中,FPGA本身是基于RAM工艺的器件,因此掉电后会丢失芯片内的程序,需要重新烧写程序。但是当程序需要投入使用时不能每一次都使用JTAG接口下载程序,一般FPGA的外围会…...

HCIA笔记3--TCP-UDP-交换机工作原理
1. tcp协议 可靠的连接 1.1 报文格式 1.2 三次握手 1.3 四次挥手 为什么TIME_WAIT需要2MSL的等待时间? (a) 为了实现可靠的关闭 (b)为了让过期的报文在网络上消失 对于(a), 假设host发给server的last ack丢了。 ser…...
计算机网络的功能
目录 信息交换 资源共享 分布式处理 可靠性增强 集中管理 信息交换 计算机网络最基本的功能之一是允许不同设备之间的数据通信。这包括电子邮件的发送和接收、即时消息的传递、文件传输等。通过网络,用户可以轻松地与全球各地的其他人进行沟通和协作。 信息交…...

Redis设计与实现第14章 -- 服务器 总结(命令执行器 serverCron函数 初始化)
14.1 命令请求的执行过程 一个命令请求从发送到获得回复的过程中,客户端和服务器都需要完成一系列操作。 14.1.1 发送命令请求 当用户在客户端中输入一个命令请求的时候,客户端会把这个命令请求转换为协议格式,然后通过连接到服务器的套接字…...

多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测
多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测 目录 多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现TCN-GRU时间卷积…...

windows安全中心,永久卸载工具分享
使用方法 2024Goby红队版工具分享,附2024年漏洞POC下载 下载链接: https://pan.quark.cn/s/4fc2712a2afc一路回车,选项Y即可 耐心等待几秒种,自动重启 此时打开windows安全中心,已经完全不能使用了,响应…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...