一、下载image_common包并编译
下载包
git clone https://github.com/ros-perception/image_common.git
将包image_common / image_transport / tutorial 文件夹复制到你的工作空间的src下,并进行编译 catkin_make。
还有一种操作 在workspace的src下创建软链接。
ln -s`pwd` / image_common / image_transport / tutorial / ./src/image_transport_tutorial
可参考官方链接:
http://wiki.ros.org/image_transport/Tutorials/PublishingImages
(包含从网络摄像头添加视频流 博主暂时未实践)
二、image_transport_tutorial包
使用image_transport_tutorial中的代码进行图像转换
参考链接:http://wiki.ros.org/image_transport/Tutorials/ExaminingImagePublisherSubscriber
publisher 发布者的命令:
roscore ## 启动ros
rosrun image_transport_tutorial my_publisher path/to/some/image.jpg ## path是绝对路径
rostopic list //查看话题 ## 如果出现 /camera/image 话题发布成功
rostopic echo /camera/image ## 展示话题信息 /camera/image 消息类型为sensor_msgs/Image
subscriber 订阅者的命令:
rosrun image_transport_tutorial my_subscriber ##订阅话题/camera/image
rosrun rqt_graph rqt_graph ## 展示ros节点关系
三、代码分析
my_publisher.cpp
重点两句话:
cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
//读图像
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
//图像转换
全部代码:
#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)
{
//Node initialization with three parameters
ros::init(argc, argv, "image_publisher");
ros::NodeHandle nh;
//ros nodehandle link with imagetransport
image_transport::ImageTransport it(nh);
//topic name is camera/image,the publish message queue size is 1.
image_transport::Publisher pub = it.advertise("camera/image", 1);
//read image,argv[1] is a path that image put in.
//use cv_bridge function make image transport to sensor_msgs.
cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
ros::Rate loop_rate(0.5);
while (nh.ok()) {
//public message
pub.publish(msg);
//wait a callback function which handle subscription nodes(this code don't subscrip message)
ros::spinOnce();
//sleep 1/0.5=2s
loop_rate.sleep();
}
}
my_subscriber.cpp
订阅者代码功能:仅展示图片。
#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);
//展示图片
cv::waitKey(10);
}
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");
}