ros发布和订阅图像的压缩——高效图传(适用带宽不足问题)

2023-05-16

ros话题机制默认通过TCP进行传输
因此特别容易堵塞。。。。。。
必须要有compressed的图像, img_raw传输速度非常慢
参考:https://blog.csdn.net/qq_30460905/article/details/107301868?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allfirst_rank_v2~rank_v25-1-107301868.nonecase&utm_term=ros%E5%8E%8B%E7%BC%A9%E5%9B%BE%E5%83%8F

1 订阅和发布简单的压缩图像(不可调压缩比)

1.1 订阅者压缩图像:

https://answers.ros.org/question/314979/decompress-jpeg-depth-data/

#include <image_transport/image_transport.h>

void saveIMage3(const sensor_msgs::Image::ConstPtr& msg)
{
}

ros::NodeHandle n;
image_transport::ImageTransport it(n);
image_transport::Subscriber itSub = it.subscribe( "usb_cam/image_raw",1,&saveIMage3,image_transport::TransportHints("compressed"));

在qt中要加入LIBS += /opt/ros/melodic/lib/libimage_transport.so 不用qt的忽略这句话。。

这样在ros中就直接产生了此话题:/usb_cam/image_raw/compressed 就是压缩图像

但是这里的回调函数没法使用boost::bind,使用后会报错,只能简单订阅sensor_msgs::Image::ConstPtr这一个参数给回调函数。

1.2 发布者压缩图像:

  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher image_pub;
  image_pub = it.advertise("image_compressed",1);
  image_pub.publish( ... );

其中…代表一个sensor_msgs::Image或者sensor_msgs::Image::ConstPtr
因此如果需要cv::Mat的发布,需要有优先转换为sensor_msgs::Image
具体转换方法:https://blog.csdn.net/weixin_44684139/article/details/108759860

2 rqt_reconfigure设置压缩比

可以用rqt_reconfigure设置压缩比:

rosrun rqt_reconfigure rqt_reconfigure

根据format调节quality或level即可。

注意,这种方法并不是只能使用rqt_image_view进行观测才能改画质,而是直接在ros系统中更改的参数。
在这里插入图片描述

3 利用Opencv提供的imencode和imdecode进行图像视频传输(Linux下)

参考https://blog.csdn.net/qq_37406130/article/details/78820176

3.1 发送端,先订阅图像,然后压缩并发布

#ifdef _WIN32	
#define  _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
#else
#include <unistd.h>//Linux系统下网络通讯的头文件集合
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <opencv2/opencv.hpp>  
// #include <opencv2/imgproc/imgproc.hpp> 
#include "ros/ros.h"
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include "sensor_msgs/CompressedImage.h"
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
// #include <opencv2/imgproc/imgproc.hpp>
// #include "opencv2/opencv.hpp"
#include <image_transport/image_transport.h>   //image_transport

using namespace cv;
using namespace std;

enum
{
	PORT = 0X4321
};
sockaddr_in m_servaddr;
int m_sockClient;

void saveIMage(const sensor_msgs::CompressedImage::ConstPtr& msg)
{

    try
    {

        cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(msg,  sensor_msgs::image_encodings::TYPE_8UC3);
    //    std::cout<<"转换成功!!!!!!!!!!!!!!!!!!!!!!!"<<std::endl;
        cv::Mat img__ = cv_ptr->image;
        cv::cvtColor(img__, img__, CV_BGR2RGB);

		// -----------------------------------------------------------------------------------------
		std::vector<uchar> data_encode;
		std::vector<int> quality;
		quality.push_back(CV_IMWRITE_JPEG_QUALITY);
		quality.push_back(50);//进行50%的压缩
		imencode(".jpg", img__, data_encode,quality);//将图像编码
		char encodeImg[65535];

		int nSize = data_encode.size();
		for (int i = 0; i < nSize; i++)
		{
			encodeImg[i] = data_encode[i];
		}
		m_servaddr.sin_addr.s_addr = inet_addr("192.168.43.103");
		m_servaddr.sin_port = htons(0x1234);//设置需要发送的IP和端口号
		sendto(m_sockClient, encodeImg, nSize, 0, (const sockaddr*)& m_servaddr, sizeof(m_servaddr));
		std::cout<<"发送成功"<<std::endl;
		memset(&encodeImg, 0, sizeof(encodeImg));  //初始化结构体
	// -----------------------------------------------------------------------------------------
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

}


int main(int argc, char** argv)
{
#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(0x01, &wsaData); //创建初始化句柄
#endif

	if ((m_sockClient = socket(AF_INET, SOCK_DGRAM, 0)) < 0)    //创建socket句柄,采用UDP协议
	{
		printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
		return -1;
	}
	memset(&m_servaddr, 0, sizeof(m_servaddr));  //初始化结构体
	m_servaddr.sin_family = AF_INET;           //设置通信方式
	m_servaddr.sin_port = htons(PORT);         //设置端口号

	bind(m_sockClient, (sockaddr*)&m_servaddr, sizeof(m_servaddr));//绑定端口号
	// VideoCapture capture(0);//打开摄像头
	// Mat image;

    ros::init(argc, argv, "talker_main");
    ros::NodeHandle n;

   //ros::Subscriber image_sub_ = n.subscribe<sensor_msgs::CompressedImage>("her/usb_cam/image_raw/compressed", 1,saveIMage);
   ros::Subscriber image_sub_ = n.subscribe<sensor_msgs::CompressedImage>("/usb_cam/image_raw/compressed", 1,saveIMage);

	ros::spin();

	return 0;
}

发送端CMakeLists.txt随便写了以下,可能不是特别严格

set( CMAKE_CXX_FLAGS "-std=c++11")

cmake_minimum_required( VERSION 2.8 )
project( send_receive )

set(OpenCV_DIR "usr/local/opencv3/share/OpenCV")

# 寻找OpenCV库
find_package( OpenCV 3 REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )


find_package(catkin REQUIRED COMPONENTS geometry_msgs sensor_msgs std_msgs robot_state_publisher urdf move_base_msgs visualization_msgs cv_bridge  image_transport)

catkin_package(
    CATKIN_DEPENDS robot_state_publisher urdf geometry_msgs sensor_msgs std_msgs move_base_msgs visualization_msgs sensor_msgs cv_bridge image_transport
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)

# 可执行程序
add_executable( send send.cpp )
# 链接OpenCV库
target_link_libraries( send ${OpenCV_LIBS} ${catkin_LIBRARIES})

3.2 接收端,接受图像并显示

#include <iostream>
#include <opencv2/opencv.hpp>  
#include <opencv2/imgproc/imgproc.hpp> 
#include <unistd.h>//Linux系统下网络通讯的头文件集合
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>
#include <fcntl.h>

using namespace cv;
using namespace std;

enum
{
	PORT = 0x1234
};
int main(int argc, char** argv)
{
	//WSADATA wsaData;
	//WSAStartup(0x01, &wsaData); //创建初始化句柄

	int m_sockClient;
	if ((m_sockClient = socket(AF_INET, SOCK_DGRAM, 0)) < 0)    //创建socket句柄,采用UDP协议
	{
		printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
		return -1;
	}
	sockaddr_in m_servaddr;
	memset(&m_servaddr, 0, sizeof(m_servaddr));  //初始化结构体
	m_servaddr.sin_family = AF_INET;           //设置通信方式
	m_servaddr.sin_port = htons(PORT);         //设置端口号

	bind(m_sockClient, (sockaddr*)&m_servaddr, sizeof(m_servaddr));//绑定套接字
	Mat image;
	char buf[65536];
	while (true)
	{
		std::vector<uchar> decode;

		int n = recv(m_sockClient, buf, sizeof(buf), 0);//接受缓存
		int pos = 0;
		while (pos < n)
		{
			decode.push_back(buf[pos++]);//存入vector
		}
		buf[n] = 0;
		image = imdecode(decode, CV_LOAD_IMAGE_COLOR);//图像解码
		imshow("image", image);
		waitKey(30);
	}
	return 0;
}


接收端CMakeLists.txt

set( CMAKE_CXX_FLAGS "-std=c++11")

cmake_minimum_required( VERSION 2.8 )
project( receive )

set(OpenCV_DIR "usr/local/opencv3/share/OpenCV")

# 寻找OpenCV库
find_package( OpenCV REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )
# 可执行程序
add_executable( receive receive.cpp )
# 链接OpenCV库
target_link_libraries( receive ${OpenCV_LIBS} )

4 ROS传输图像带宽不够用的解决方法(realsenseD415压缩图像)

https://blog.csdn.net/qq_23670601/article/details/98939712?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ros发布和订阅图像的压缩——高效图传(适用带宽不足问题) 的相关文章

  • 第六篇,STM32脉冲宽度调制(PWM)编程

    1 PWM概念 PWM叫脉冲宽度调制 Pulse Width Modulation xff0c 通过编程控制输出方波的频率和占空比 高低电平的比例 xff0c 广泛应用在测量 xff0c 通信 xff0c 功率控制等领域 呼吸灯 xff0c
  • ovn 配置逻辑路由器实现三层转发

    本文使用ovn搭建一个三层转发的环境 xff0c 拓扑图如下 image png 两个虚拟交换机ls1和ls2 xff0c 端口ip网段分别为 10 10 10 0 24和 10 10 20 0 24 虚拟交换机上分别连接两个vm 使用na
  • 第十篇,STM32串口蓝牙编程

    1 串口蓝牙概念 串口蓝牙是一个蓝牙模块 xff0c 内部有蓝牙模块和程序 xff0c 可以进行蓝牙通信 xff0c 同时提供一个串口接口 xff0c 通过串口可以配置蓝牙模块进行数据传输 2 使用串口3连接蓝牙模块 3 手机上安装蓝牙调试
  • 第十四篇,STM32的CAN总线通信

    1 CAN总线的概念 CAN指的是控制器局域网网络 Controller Area Network xff0c 由德国博世汽车电子厂商开发出来 CAN使用差分信号 xff0c 具有较强的抗干扰能力和传输稳定性 CAN属于多主通信 xff0c
  • OpenCV图像处理学习十九,像素重映射cv::remap

    一 像素重映射概念 重映射就是把输入图像中各个像素按照制定的规则顺序映射到另外一张图像的对应位置上去 xff0c 形成一张新的图像 二 像素映射API函数接口 cv remap xff08 InputArray src 输入图像 Outpu
  • OpenCV图像处理学习二十一,直方图比较方法

    一 直方图比较 直方图比较是对输入的两张图像进行计算得到直方图H1与H2 xff0c 归一化到相同的尺度空间 xff0c 然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度 xff08 每张图像都有唯一的直方图与之对应 xff0
  • 嵌入式FreeRTOS学习八,xTaskCreate创建任务的细节以及恢复中断任务实现

    一 创建任务函数xTaskCreate 任务也不是很复杂的东西 xff0c 任务也就是一个函数xTaskCreate 简单得说 xff0c 创建一个任务 xff0c 你得提供它的执行函数 xff0c 你得提供它的栈的大小 xff0c 函数的
  • 嵌入式FreeRTOS学习一,FreeRTOS概述和代码结构

    一 FreeRTOS是什么 FreeRTOS 是由 Real Time Engineers Ltd 出品 xff0c 是一款市场领先的 RTOS 现在已经支持几十种 处理器架构 Free即免费的 xff0c RTOS全称是 Real Tim
  • 嵌入式FreeRTOS学习二,FreeRTOS任务的创建和删除

    一 任务的创建和删除 1 1 函数xTaskCreate 此函数用来创建一个任务 xff0c 任务需要RAM来保存与任务有关的状态信息 任务控制块 xff0c 任务也需要一定的RAM 来作为任务堆栈 如果使用函数xTaskCreate 来创
  • 嵌入式FreeRTOS学习五,FreeRTOS任务调度器

    四 调度器 FreeRTOS 操作系统支持三种调度方式 xff1a 抢占式调度 xff0c 时间片调度和合作式调度 实际应用主要是抢占式调度和时间片调度 xff0c 合作式调度用到的很少 启动调度器的API函数vTaskStartSched
  • 嵌入式FreeRTOS学习九,任务链表的构成,TICK时间中断和任务状态切换调度

    一 tskTaskControlBlock 函数结构体 在tskTaskControlBlock 任务控制块结构体中 xff0c 其中有任务状态链表和事件链表两个链表成员 xff0c 首先介绍任务状态链表这个结构 xff0c 这个链表通常用
  • 嵌入式FreeRTOS学习十,任务调度和任务就绪链表任务调度过程

    一 main函数里面的栈是哪里分配的 main函数里面用到的栈 xff0c 假设为msp 是汇编代码里面设定的 xff0c 对于STM32F103 在汇编代码里的向量表设置了一个栈 initial sp 那这个栈是给谁用的呢 xff1f 可
  • ovn 通过网关虚拟路由器连接外部网络

    本文实验如何通过ovn的网关逻辑路由器将ovn网络连接到外部网络 前面讲过ovn的逻辑路由器是分布式的 xff0c 这意味着它没有绑定到某个节点上 xff0c 而是存在于所有节点上的 xff0c 同时它是通过每个节点的openflow流表来
  • 嵌入式FreeRTOS学习十一,深入理解任务调度机制

    一 任务调度机制 可抢占 xff1a 高优先级的任务先运行时间片轮转 xff1a 同优先级的任务轮流执行空闲任务礼让 xff1a 如果有同是优先级为0的其他就绪任务 xff0c 空闲任务主动放弃一次运行机会函数调用vTaskDelay xD
  • SOAP传输协议

    一 HTTP传输协议 超文本传输协议 xff08 HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 xff0c 它是基于请求 响应的模式协议 xff0c 客户端发出请求 xff0c
  • ONVIF简介

    一 什么是ONVIF ONVIF规范描述了网络视频的模型 接口 数据类型以及数据交互的模式 并复用了一些现有的标准 xff0c 如WS系列标准等 ONVIF规范的目标是实现一个网络视频框架协议 xff0c 使不同厂商所生产的网络视频产品 x
  • gsoap工具生成onvif设备搜索(remotediscovery)代码框架

    什么是gsoap工具 xff1f gSOAP 提供了两个工具来方便开发人员使用 C C 43 43 语言快速开发Web 服务应用 xff0c 通过 gSOAP 提供的这两个工具 xff0c 开发人员可以快速生成服务端与客户端代码框架 xff
  • 001_初识_飞航科技光标飞控

    这两天老潘给我一块飞控 xff0c 让我练手 xff0c 为电赛做准备 xff0c 拿到控挺开心的 xff0c 毕竟省了一笔RMB 本来想着买块正点原子的飞控 资料 xff1a 说起资料简单看了一下发现还蛮全的 xff0c 但是这个资料我居
  • 写出C语言的第一个程序“Hello World”

    这里写自定义目录标题 写出C语言的第一个程序 Hello World 写出C语言的第一个程序 Hello World 下面展示一些 内联代码片 span class token comment A code block span span
  • Eigen库的安装攻略

    Eigen库的安装攻略 转载 xff1a Eigen库安装 xff08 两种方式 xff09 转载 xff1a Eigen库安装 xff08 两种方式 xff09 链接 link

随机推荐

  • 【ROS2基础学习】

    入门篇 前言一 创建一个功能包二 编译三 source总结 前言 提示 xff1a 这里是记录的大概内容 xff1a 随着机器人技术的不断发展 xff0c ROS也越来越重要 xff0c 很多人都开启了学习ROS xff0c 本文就介绍了R
  • Arduino 外部中断重置内部定时器

    Arduino 外部中断重置内部定时器 文章目录 Arduino 外部中断重置内部定时器前言一 准备工作二 代码三 实验效果1 设置1Hz的方波 xff08 外部中断触发 xff09 xff1a 2 观察示波器各个波形 xff1a 3 延迟
  • ALUBI LPMS-IG1 RS232 IMU ROS2驱动安装

    文章目录 前言一 下载官方系列文档二 windows上的上位机程序安装2 Ubuntu上的ROS2驱动安装Offset Mode 2 总结 前言 IMU在自动驾驶领域广泛应用 xff0c 本文主要记录了在ROS2中使用ALUBI LPMS
  • ovn-northd 源码分析

    ovn northd是ovn中的核心后台进程 xff0c 主要负责将ovn的高层配置转换成供ovn controller后台进程使用的逻辑配置 xff0c 更详细的说就是它将ovn northbound数据库中传统意义上的逻辑网络配置转换成
  • 镭神CH128x1系列激光雷达使用记录

    镭神CH128x1系列激光雷达使用记录 文章目录 镭神CH128x1系列激光雷达使用记录前言一 操作步骤1 PC连接雷达 二 实验1 雷达控制器上的接口 xff1a 2 接口定义3 Rviz中显示效果 总结致谢 前言 本条博客的需求来源于自
  • c语言中char数组的结束位

    因为是半路出家学习cpp的 xff0c 所以经常会对c语言里面的字符数组感到困惑 xff0c 这次一次性做个总结 首先 xff0c 结束位 0 只针对字符数组 xff0c 不针对整型或者其他数组 其次 xff0c 字符数组的大小只针对里面的
  • SUMO 使用netconvert报错解决办法

    SUMO 使用netconvert报错 问题描述正确解决方法不适用的解决方法 问题描述 刚开始学习使用sumo xff0c 版本是sumo1 8 0 第一次使用netconvert转换地图时出现报错 xff0c 提示没有PROJ Libra
  • IoTDB基础 初识IoTDB 安装及基本使用(个人学习记录)

    官方文档 http iotdb incubator apache org zh UserGuide V0 13 x API Programming Java Native API html 参考博客 时序数据库IoTDB安装及基本使用htt
  • 树莓派+ L298N 控制二相四线步进电机

    树莓派 43 L298N 控制二相四线步进电机 1 步进电机 步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机 在非超载的情况下 xff0c 电机的转速 停止的位置只取决于脉冲信号的频率和脉冲数 xff0c 而不受负载变化的影响
  • VTK移动立方体法处理CT图像建立三维模型

    span class token comment 移动立方体 span span class token macro property span class token directive keyword include span span
  • 使用tcp工具调试socket服务端通信

    背景介绍 xff1a 客户端是用tcp连接调试 xff0c 工具链接 https pan baidu com s 1kfjv1jdS8KJgb7YVSu9Wtw 提取码 z34a 服务端是Java代码写的逻辑 xff0c 用byte 流接收
  • Fast Planner 轨迹规划

    文章目录 0 概览1 关键问题2 相关工作3 F a s t P
  • C++继承和多态学习心得

    继承 定义 xff1a 在已有类的基础上创建新类的过程 一个 B 类继承A类 xff0c 或称从类 A 派生类 B 类 A 称为基类 xff08 父类 xff09 xff0c 类 B 称为派生类 xff08 子类 xff09 语法形式 xf
  • Python学习笔记(六):isalpha()函数的用法

    isalpha 方法 xff1a 判断字符串是否只由字母组成 xff0c 如果字符串中所有字符都是字母则返回True xff0c 否则返回False str1 61 34 python 34 print str1 isalpha True
  • ovn-controller源码分析

    ovn controller是运行在chassis hypervisor上的后台进程 xff0c 向上通过OVSDB协议连接到OVN sourthbound数据库 xff0c 向下通过OVSDB协议连接到ovs数据库 xff0c 并通过op
  • ROS学习笔记(十一) rospy介绍(一)

    rospy介绍 xff08 一 xff09 rospy是Python版本的ROS客户端库 xff0c 提供了Python程序需要的接口 xff08 rospy就是一个Python模块 xff09 xff0c 位于 opt ros kinee
  • ROS学习笔记(十三) TF介绍(一)

    TF介绍 xff08 一 xff09 TF xff1a 机器人不停部位之间的坐标转换 坐标转换包括位置和姿态两方面 xff0c ROS中的tf是一个让用户随时记录多个坐标系的软件包 tf保持缓存的树形结构中的坐标系之间的关系 xff0c 并
  • SLAM基础(三) --图优化

    滤波器的缺点 xff1a EKF SLAM不仅要维护自身的状态 xff0c 还需要维护地图 xff08 特征 xff09 于是必须在内存上做出牺牲 xff0c 比如500个特征 xff0c 每个特征在二维环境中是两个点 xff08 x轴 y
  • 前端JS十种继承方式-图解通俗易懂

    1 学习JS继承一定要拿指针的概念去审视 xff0c 不能死记 2 首先要明白 xff1a 原型 xff08 对象 xff09 xff0c let a 61 new A 会发生构成原型链图 xff0c 类对象的prototype指向他的原型
  • ros发布和订阅图像的压缩——高效图传(适用带宽不足问题)

    ros话题机制默认通过TCP进行传输 因此特别容易堵塞 必须要有compressed的图像 xff0c img raw传输速度非常慢 参考 xff1a https blog csdn net qq 30460905 article deta