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_transportusing 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 _WIN32WSADATA wsaData;WSAStartup(0x01, &wsaData); //创建初始化句柄
#endifif ((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

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

  1. ROS学习笔记九:用C++编写ROS发布与订阅

    ROS学习笔记九:用C++编写ROS发布与订阅 本节主要介绍如何用C++编写一个简单的ROS发布与订阅. 编写发布节点 在之前创建的例子beginner_tutorials软件包中,在其目录下的src ...

  2. ROS学习笔记四:用C++编写ROS发布与订阅

    一.创建并编译功能包 1.1 创建功能包 在工作空间的 src 目录下创建功能包: $ cd ~/dev/catkin_ws/src $ catkin_create_pkg chapter2_tuto ...

  3. ROS发布/订阅Float64MultiArray数组类消息(C++和Python相互发布和订阅)

    在terminal用指令发布一个Float64MultiArray消息,这个在调试时特别好用,注意格式,最后一行的data: [1,2,3]中冒号和后面的中括号间要有空格 rostopic pub / ...

  4. ros 发布信息频率_ROS:消息发布器和订阅器(c++)

    学习资料主要源自http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29 $ roscd beginner_t ...

  5. ros订阅话题python_ROS之话题的发布与订阅

    消息: msg文件就是一个描述ROS中所使用消息类型的简单文本.它们会被用来生成不同语言的源代码. 注意,在构建的时候,我们只需要"message_generation".然而,在 ...

  6. ROS入门学习笔记|话题发布与订阅

    文章目录 一.工作空间 1.创建一个名称为sor_ws的工作空间 2.编译工作空间 3.创建功能包 二.自定义话题消息 1.定义msg文件 2.配置package.xml和CMakeLists.txt ...

  7. ROS踩坑笔记2-基于海曼红外测温仪的消息发布与订阅

    系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮 ...

  8. opencv 读取相机图像+ros发布图像

    #!/usr/bin/python2 # coding=utf-8import cv2 import numpy as np from std_msgs.msg import Header from ...

  9. 使用ros发布UVC相机和串口IMU数据

    1.目的:为了可以标定普通USB相机和固定在相机上的外置IMU的外参,我希望通过ROS获取更高分辨率和更高频率的图像数据,并且可以将图像和imu的topic发布出来,直接使用rosbag record ...

最新文章

  1. 环形动画加载视图AnimatedCircleLoadingView​​​​​​​
  2. C# 5.0中引入了async 和 await
  3. TimeoutException
  4. ffmpeg openh264
  5. C++的三大特性:封装,继承,多态
  6. HDU ACM 1046 Gridland 找规律
  7. JS中点语法和方括号语法访问属性的区别
  8. spring 注入bean的两种方式
  9. Hadoop辅助工具——Flume、Sqoop
  10. Spring MVC:MySQL和Hibernate的安全性
  11. bing搜索引擎入口_互联网流量入口——头条的搜索计划
  12. exec 与shell_exec的区别
  13. 十大漏洞破解网吧管理软件(1)
  14. Thinkpad部分软件相关服务进程的总结
  15. 玩转亚马逊 AWS IoT(3): SpringBoot 2.7 集成 AWS IoT 服务
  16. x64dbg 配置插件SDK开发环境
  17. 南京大学计算机专业拂晓,南京大学2020年计算机学科录取推免生222人,全部来自211高校...
  18. 01_03 获取答案
  19. SQL/MYSQL在CMD命令操作符中创建数据库 、表单并插入数据查看
  20. 蓝牙【GATT】协议介绍

热门文章

  1. Android 控件view的可见,不可见,隐藏的设置和区别
  2. 2022年12月国产数据库大事记-墨天轮
  3. xctf攻防世界 CRYPTO高手进阶区 sherlock
  4. element UI 表单自定义验证,css水平且垂直居中方法
  5. 自定义 “至今”选项日期选择器
  6. 荣耀V40最新消息 升级系统该如何更新
  7. 技术驱动下的电视行业,HDR成为下一个风口
  8. (2016)最新最好的Unity3D Github项目收集
  9. 数据库保存表情符号(emoji)
  10. SeaTunnel 2.1.2的源码解析(5)seatunnel-connectors-flink-http