ros2教程(一):使用python和C++发布摄像头原始图像和压缩图像
1. 使用python发布图像
在ROS 2中,可以通过使用rclpy库来发布压缩图像和原始图像。发布原始图像可以使用sensor_msgs.msg.Image消息类型,压缩图像则使用sensor_msgs.msg.CompressedImage消息类型。
#!/usr/bin/env python3# function: usbcam publish raw image or compressed image
# author: xxx
# Date: 2024.06.29
# version: v0.1import rclpy
from rclpy.node import Node
import cv2
from cv_bridge import CvBridge, CvBridgeError
import numpy as np
import time
from sensor_msgs.msg import Image, CompressedImageclass NodePublisher(Node):def __init__(self,name):super().__init__(name)self.get_logger().info("usb cam node created!")def main(args=None):#image sizeheight = 480width = 640#capture frequencyfrequency = 10#compressed flagcompressed_flag = True#image compressed quality %img_quality = 50 #usb cam device idcapture = cv2.VideoCapture(0)#ubuntu: check /dev/video*capture.set(cv2.CAP_PROP_FRAME_WIDTH, width) capture.set(cv2.CAP_PROP_FRAME_HEIGHT, height)capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # init rclpy noderclpy.init()node = NodePublisher("usb_cam_image") if compressed_flag: # create compressed image topicsimage_compressed_pub = node.create_publisher(CompressedImage, "/usb_cam_image/compressed", 10) else: # create raw image topicsimage_pub = node.create_publisher(Image, "/usb_cam_image", 10) # create compressed image messagemsg_compressed_img = CompressedImage()msg_compressed_img.format = "jpeg"bridge = CvBridge() n = 30 // frequencycount = 0while True: ret, frame = capture.read() if count % n == 0:np_frame = np.array(cv2.flip(frame, 1)) if compressed_flag:_, compressed_image = cv2.imencode('.jpg', np_frame, [int(cv2.IMWRITE_JPEG_QUALITY), img_quality])msg_compressed_img.data = compressed_image.tobytes() image_compressed_pub.publish(msg_compressed_img) else: img_raw = bridge.cv2_to_imgmsg(np_frame, encoding="bgr8") image_pub.publish(img_raw) count = 0count += 1
相应的setup.py文件如下:
from setuptools import setuppackage_name = 'py_usb_cam_record'setup(name=package_name,version='0.0.0',packages=[package_name],data_files=[('share/ament_index/resource_index/packages',['resource/' + package_name]),('share/' + package_name, ['package.xml']),],install_requires=['setuptools'],zip_safe=True,maintainer='xxx',maintainer_email='xxx@gmail.com',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts': ['py_usb_cam_record = py_usb_cam_record.py_usb_cam_record:main'],},
)
2. 使用C++发布图像
在ROS 2中,使用C++发布原始图像和压缩图像可以通过image_transport库来实现,原始图像使用sensor_msgs::msg::Image,而压缩图像可以通过image_transport::Publisher发布为sensor_msgs::msg::CompressedImage。
使用C++发布原始图像
/*=================================================* function: usbcam publish raw image or compressed image
* Author: xxx
* Date: 2024.06.29===================================================*/#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"
#include "opencv2/opencv.hpp"
#include "cv_bridge/cv_bridge.h"using namespace std::chrono_literals;class CameraPublisher : public rclcpp::Node {
public:CameraPublisher(): Node("camera_publisher"), count_(0) {publisher_ = this->create_publisher<sensor_msgs::msg::Image>("camera/image", 10);timer_ = this->create_wall_timer(100ms, std::bind(&CameraPublisher::publishImage, this));cap_ = cv::VideoCapture(0); // Open default cameraprintf("record raw image!\n");if (!cap_.isOpened()) {RCLCPP_ERROR(this->get_logger(), "Failed to open camera");}}private:void publishImage() {cv::Mat frame;cap_ >> frame; // Capture a frame from the cameraif (frame.empty()) {RCLCPP_ERROR(this->get_logger(), "Failed to capture frame");return;}cv::Mat resized_frame;cv::resize(frame, resized_frame, cv::Size(640, 480), cv::INTER_LINEAR);auto msg = cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", resized_frame).toImageMsg();publisher_->publish(*msg);count_++;printf("record raw image: %d\r", count_);}rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;cv::VideoCapture cap_;int count_;
};int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = std::make_shared<CameraPublisher>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}
使用C++发布压缩图像
/*=================================================* function: usbcam publish raw image or compressed image
* Author: xxx
* Date: 2024.06.29===================================================*/// ros2 run image_transport republish compressed in/compressed:=compressed_image raw out:=image_raw#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/compressed_image.hpp"
#include "opencv2/opencv.hpp"
#include "cv_bridge/cv_bridge.h"using namespace std::chrono_literals;class CameraPublisher : public rclcpp::Node {
public:CameraPublisher(): Node("camera_publisher"), count_(0) {publisher_ = this->create_publisher<sensor_msgs::msg::CompressedImage>("compressed_image", 10); timer_ = this->create_wall_timer(100ms, std::bind(&CameraPublisher::publishImage, this));cap_ = cv::VideoCapture(0); // Open default cameraprintf("record compressed image!\n");if (!cap_.isOpened()) {RCLCPP_ERROR(this->get_logger(), "Failed to open camera");}}private:void publishImage() {cv::Mat frame;cap_ >> frame; // Capture a frame from the cameraif (frame.empty()) {RCLCPP_ERROR(this->get_logger(), "Failed to capture frame");return;}cv::Mat resized_frame;cv::resize(frame, resized_frame, cv::Size(640, 480), cv::INTER_LINEAR);std::vector<uchar> buf;cv::imencode(".jpg", resized_frame, buf, {cv::IMWRITE_JPEG_QUALITY, 80}); // Adjust JPEG quality (0-100 scale)sensor_msgs::msg::CompressedImage msg;msg.format = "jpeg";msg.data = buf;publisher_->publish(msg);count_++;printf("record compressed image: %d\r", count_);}rclcpp::Publisher<sensor_msgs::msg::CompressedImage>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;cv::VideoCapture cap_;int count_;
};int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = std::make_shared<CameraPublisher>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}
CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.5)
project(usb_cam_record)# Default to C++14
if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)
endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(image_transport REQUIRED)
find_package(cv_bridge REQUIRED) # If using OpenCV for image handling
find_package(OpenCV REQUIRED)#include_directories(${OpenCV_INCLUDE_DIRS})add_executable(usb_cam_record_raw_node src/usb_cam_record_raw.cpp)
add_executable(usb_cam_record_compressed_node src/usb_cam_record_compressed.cpp)ament_target_dependencies(usb_cam_record_raw_noderclcppsensor_msgscv_bridgeimage_transportOpenCV
) ament_target_dependencies(usb_cam_record_compressed_noderclcppsensor_msgscv_bridgeimage_transportOpenCV
) install(TARGETS usb_cam_record_raw_node usb_cam_record_compressed_nodeDESTINATION lib/${PROJECT_NAME})if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# uncomment the line when a copyright and license is not present in all source files#set(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# uncomment the line when this package is not in a git repo#set(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()
package.xml的文件配置如下:
<package format="3">
<name>usb_cam_record</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="xxx@gmail.com">xxx</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<build_depend>rclcpp</build_depend>
<exec_depend>rclcpp</exec_depend>
<build_depend>sensor_msgs</build_depend>
<exec_depend>sensor_msgs</exec_depend>
<build_depend>image_transport</build_depend>
<exec_depend>image_transport</exec_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>相关文章:
ros2教程(一):使用python和C++发布摄像头原始图像和压缩图像
1. 使用python发布图像 在ROS 2中,可以通过使用rclpy库来发布压缩图像和原始图像。发布原始图像可以使用sensor_msgs.msg.Image消息类型,压缩图像则使用sensor_msgs.msg.CompressedImage消息类型。 #!/usr/bin/env python3# function: usbcam publish r…...
【自动化测试】UI自动化的分类、如何选择合适的自动化测试工具以及其中appium的设计理念、引擎和引擎如何工作
引言 UI自动化测试主要针对软件的用户界面进行测试,以确保用户界面元素的交互和功能符合预期 文章目录 引言一、UI自动化的分类1.1 基于代码的自动化测试1.2 基于录制/回放的自动化测试1.3 基于框架的自动化测试1.4 按测试对象分类1.5 按测试层次分类1.6 按测试执行…...
深入理解Python中的“_,”:一个实用的语法特性
在Python编程中,你可能经常会看到一个特殊的标识符“_”。这个符号在Python中有多种用途,其具体含义依上下文而定。本文将探讨其中一种常见用法——作为一个临时性的占位符——并解释它在实际编程中的实用性和应用场景。 1. “_”作为占位符 在Python中…...
Mac清理其他文件:释放存储空间的高效指南
每个Mac用户都可能遇到存储空间不足的问题,尤其是当“其他”文件积累到一定体积时。在Mac上,“其他”文件通常包括各种系统文件、缓存、文档以及不被归类为应用程序、照片、电影或音乐的其他类型的文件。这些文件往往不易被注意,但逐渐占用了…...
html+css+js网页设计 旅游 龙门石窟4个页面
htmlcssjs网页设计 旅游 龙门石窟4个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...
CISSP一站通关
依托轻速云维护了一个专注于CISSP备考通关的在线学习平台,提供知识串讲视频,配合大量针对性的习题和重难点习题解析,帮助备考学习者高效学习和巩固知识点。已经帮助100考友顺利通过考试。 知识串讲视频是我主讲的5天直播课程的录屏࿰…...
Golang | Leetcode Golang题解之第406题根据身高重建队列
题目: 题解: func reconstructQueue(people [][]int) (ans [][]int) {sort.Slice(people, func(i, j int) bool {a, b : people[i], people[j]return a[0] > b[0] || a[0] b[0] && a[1] < b[1]})for _, person : range people {idx : pe…...
【我的Android进阶之旅】解决CardView四个圆角有白边的问题
文章目录 一、问题描述二、分析CardView出现白边的原因三、如何解决这个问题?3.1 如何修复?3.2 为什么这样可以修复?3.3 示例代码3.4 总结一、问题描述 在实现一个RecycleView的Item时候,样式需要用到卡片式效果,于是想到用CardView来实现,但是最终发现运行出来的效果,…...
学习笔记JVM篇(四)
垃圾回收器 说完垃圾回收算法接下来就需要对应的垃圾回收器去回垃圾回收器。接下来介绍几种垃圾回收器 1、Serial 串行回收器,是单线程版本,暂停所有的应用。在单CPU的情况下效率是很高的,因为不涉及线程的上下文切换。适用于小型程序和客…...
828 华为云征文|华为 Flexus 云服务器搭建萤火商城 2.0
《828 华为云征文|华为 Flexus 云服务器搭建萤火商城 2.0》 在 2024 年 9 月 14 日这个特别的日子,我着手利用华为 Flexus 云服务器搭建轻量级、高性能、前后端分离的电商系统萤火商城 2.0,开启了一段充满挑战与惊喜的旅程。 华为 Flexus 云服…...
centos7安装MySQL5.7.44
下载压缩文件 命令: #放到在/usr/local目录下 cd /usr/local #上传命令选择安装包 rz #解压缩包 tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz #给包重命名为mysql mv mysql-5.7.44-linux-glibc2.12-x86_64 mysql #查看mysql目录下有什么东西 [rootlocal…...
HTTP 请求处理的完整流程到Servlet流程图
HTTP 请求处理的完整流程。从 TCP 三次握手开始,一直到 Servlet 处理请求并返回响应。 首先,让我解释一下 response.setContentType("text/html;charsetUTF-8"); 这行代码: 这行代码设置了 HTTP 响应的 Content-Type 头。它告诉浏…...
spingboot中创建简单的WebSocket服务和使用OKHttp创建socket客户端接收数据
背景 springboot 中使用okhttp3创建webSocket服务端 server1 和客户端 client1,客户端clinet1调用server1用于发送图片,创建客户端client2接收此图片. 在Spring Boot中使用OkHttp3创建WebSocket服务端和客户端,涉及到两个不同的操作ÿ…...
Redis入门2
在java中操作Redis Redis的Java客户端 Redis 的 Java 客户端很多,常用的几种: Jedis Lettuce Spring Data Redis Spring Data Redis 是 Spring 的一部分,对 Redis 底层开发包进行了高度封装。 在 Spring 项目中,可以使用Spring Data R…...
嵌入式Linux:信号是什么?
目录 1、信号的来源 2、信号的处理方式 3、信号的异步性 4、信号编号 信号是Linux系统中用于通知进程事件发生的一种机制,可以将其视为一种软件中断。信号类似于硬件中断,能够打断进程当前的执行流程,从而实现对中断机制的一种软件层面的…...
教你搭建一个wifi贴系统
大家好,我是鲸天科技千千,大家都知道我是做小程序开发的,平时会给大家分享一些互联网相关的创业项目,感兴趣的可以跟我关注一下。 搭建一个首先就是要搭建一个自己的wifi贴小程序,我们自己的工作就是把这个小程序推广…...
C#中的LINQ语句
LINQ(Language Integrated Query)是 .NET Framework 中的一个功能强大的查询语言,它允许开发者使用类似 SQL 的语法来查询和操作数据。在 C# 中,LINQ 可以用于查询数组、列表、集合、XML 文档、关系数据库等。以下是一些常见的 LI…...
【C++】——string(模拟实现)
文章目录 string类构造string类拷贝构造string类析构string类运算符重载string类部分常用接口的模拟实现 这篇博客中构造、拷贝构造、析构、还有一些短小频繁调用的函数就不用做函数和定义分离,因为在类中,这种函数会默认是内联函数 string类构造 构造函…...
c++20 std::format 格式化说明
在标头<format>定义 ()功能很强大,它把字符串当成一个模板,通过传入的参数进行格式化,并且使用大括号‘{}’作为特殊字符代替‘%’。 1、基本用法 (1)不带编号,即“{}”(2)带…...
HTB-Unified(log4j2漏洞、MongoDb替换管理员密码)
前言 各位师傅大家好,我是qmx_07,今天给大家讲解Unified靶机 渗透过程 信息搜集 服务器开放了SSH服务,HTTP服务 访问网站 验证log4j2漏洞 8443端口:UniFi 网络 ,访问查询 是否有Nday漏洞利用 可以观察到UniFi的版…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
