在ROS中 opencv 发布和接收图像消息

1、创建相关功能包
首先进入到你的工作空间,比如我的工作空间是catkin_ws,然后进入src 目录下,使用catkin_create_pkg 命令创建你的功能包,以my_image_transport 功能包为例,注意功能包后面参数为该功能包的依赖项。

$ cd catkin_ws/
$ cd src/
$ catkin_create_pkg my_image_transport image_transport cv_bridge


然后回到工作空间内编译该功能包

$ cd ..
$ catkin_make


ps:如果不带任何参数的话,catkin_make 默认编译工作空间下的所有功能包,如果你不怕麻烦的话可以使用这个参数编译特定的功能包:
catkin_make -DCATKIN_WHITELIST_PACKAGES="package1;package2"
或者使用
catkin_make --pkg package_name
同时,更新初始化文件
$ source devel/setup.bash
2、在ROS中传递图像
在学习从摄像头获取视频之前,我们最好先学会如何发布一个图像消息,简单熟悉之后,再学习如何发布视频。
2.1、创建一个图像发布者程序
首先入功能包,创建src目录,在里面创建如下代码:

$ cd src
$ vi my_publisher.cpp


如果你已经对ros中的各种命令比较熟悉,你可以采取更简单的命令

$ rosed my_image_transport my_publisher.cpp


ps: 如果上述命令不管用,那么在运行上述命令之前最好先运行下面的命令,每次遇到类似的问题都可以运行这条命令,屡试不爽!

$ source ~/catkin_ws/devel/setup.bash


下面是my_publisher.cpp 文件里的内容。

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
 
int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);
 
  cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
  sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
 
  ros::Rate loop_rate(5);
  while (nh.ok()) {
    pub.publish(msg);
    ros::spinOnce();
    loop_rate.sleep();
  }
}


我们来一步一步地分析一下这段代码。
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
首先ros.h这个头文件是所有的ros节点中必须要包含的,下面三个分别是实现图像的发布和订阅,调用opencv库(当然前提是你在你的系统里已经安装了OpenCV),完成opencv图像格式转化为ROS图像格式所要用到的头文件。另外,在package.xml文件中我们也需要根据所需头文件配置相关的依赖。(下节我们会介绍到)
image_transport::ImageTransport it(nh);
用之前声明的节点句柄初始化it,其实这里的it和nh的功能基本一样,你可以向之前一样使用it来发布和订阅相消息。
image_transport::Publisher pub = it.advertise("camera/image", 1);
告诉节点管理器(roscore)我们要在camera/image话题上发布图像,这里第一个参数是话题的名称,第二个是缓冲区的大小(即消息队列的长度,在发布图像消息时消息队列的长度只能是1)。
cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
根据运行时给定的参数(图像文件的路径)读取图像,这是opencv里面的函数,具体可以参考opencv的相关资料。
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
将opencv格式的图像转化为ROS所支持的消息类型,从而发布到相应的话题上。
ros::Rate loop_rate(5);
  while (nh.ok()) {
    pub.publish(msg);
    ros::spinOnce();
    loop_rate.sleep();
  }
}
发布图片消息,使消息类型匹配的节点订阅该消息。
2.2、创建订阅者节点

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
 
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
  try
  {
    cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
  }
  catch (cv_bridge::Exception& e)
  {
    ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
  }
}
 
int main(int argc, char **argv)
{
  ros::init(argc, argv, "image_listener");
  ros::NodeHandle nh;
  cv::namedWindow("view");
  cv::startWindowThread();
  image_transport::ImageTransport it(nh);
  image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
  ros::spin();
  cv::destroyWindow("view");
}


  前面重复的部分这里不在赘述,我只介绍一下几段新的代码。
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
这是一个回调函数,当有新的图像消息到达camera/image时,该函数就会被调用。
cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
这段代码用于显示捕捉到的图像,其中
cv_bridge::toCvShare(msg, "bgr8")->image

用于将ROS图像消息转化为Opencv支持的图像格式(采用BGR8编码方式)。
其实这部分代码的用法恰好与上一节中发布者节点中的
CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
作用相反。
2.3、配置相关文件
在CMakeList.txt添加如下几行代码

set(OpenCV_DIR /usr/local/share/OpenCV)
message(STATUS "version: ${OpenCV_VERSION}")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(my_subscriber  src/my_subscriber.cpp)
add_executable(my_publisher   src/my_publisher.cpp)
target_link_libraries(my_subscriber  ${catkin_LIBRARIES})
target_link_libraries(my_publisher   ${catkin_LIBRARIES})
target_link_libraries(my_subscriber ${OpenCV_LIBS})
target_link_libraries(my_publisher ${OpenCV_LIBS})


配置好上述文件之后你就可以编译节点了!

$ cd ~/catkin_ws
$ catkin_make


编译成功之后你就可以运行你写好的节点了。如果没有运行成功,就检查一下相关的配置文件或者节点代码中有无错误。在运行节点之前一定要先打开节点管理器。打开终端运行roscore,然后打开另一终端运行下述命令,
 

rosrun rosopencv my_publisher /home/viki/Pictures/th.jpeg

上述命令有三个参数,分别是包名,节点名,所传递的图像的路径。如果不成功,就试试我之前提到的那个source命令。 
再打开一个终端,输入rostopic list查看当前的主题清单。 

下面运行订阅者节点,

rosrun rosopencv my_subscriber


--------------------- 
作者:博瓦 
来源:CSDN 
原文:https://blog.csdn.net/u010925447/article/details/80033288 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值