记录一下在ros中使用opencv显示图像和发布接收图像的一些步骤。
1. 准备工作
首先ubuntu16.04的ros-kinetic
版本自带opencv的所以就不用再单独安装喽。
-
修改一下CMakeLists.txt
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs sensor_msgs message_filters OpenCV cv_bridge image_transport ) find_package(PCL 1.7 REQUIRED) find_package(OpenCV REQUIRED) include_directories(include ${catkin_INCLUDE_DIRS}) include_directories(include ${OpenCV_INCLUDE_DIRS}) include_directories(include ${PCL_INCLUDE_DIRS}) add_executable(hw_opencv src/hw_opencv.cpp) target_link_libraries (hw_opencv ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})
2. 调用opencv显示图像
-
代码
#include "ros/ros.h" #include <sensor_msgs/PointCloud2.h> #include <sensor_msgs/Image.h> #include <sensor_msgs/image_encodings.h> //头文件sensor_msgs/Image是ROS下的图像的类型,这个头文件中包含对图像进行编码的函数。 #include <image_transport/image_transport.h> //这个头文件中包含的是ImageTransport类,这个类提供ROS中图像的订阅和发布。 #include <cv_bridge/cv_bridge.h> //头文件cv_bridge中包含了CvBridge类,而CvBridge中的API可以将ROS下的sensor_msgs/Image消息类型转化成cv::Mat #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace std; static const char WINDOW[] = "Image window"; int main(int argc, char **argv) { ros::init(argc, argv, "hw_opencv"); ros::NodeHandle node; cout << "\033[1;31m hw1! \033[0m" << endl; cv::Mat cv_image = cv::imread("/home/djq/me.jpg"); if(cv_image.empty() ) { ROS_ERROR("Read the picture failed!"); return -1; } // Show the image cv::namedWindow(WINDOW); cv::imshow(WINDOW,cv_image); cv::waitKey(0); return 0; }
-
效果
3. 发布图像
-
代码
#include "ros/ros.h" #include <sensor_msgs/PointCloud2.h> #include <sensor_msgs/Image.h> #include <sensor_msgs/image_encodings.h> //头文件sensor_msgs/Image是ROS下的图像的类型,这个头文件中包含对图像进行编码的函数。 #include <image_transport/image_transport.h> //这个头文件中包含的是ImageTransport类,这个类提供ROS中图像的订阅和发布。 #include <opencv2/highgui/highgui.hpp> //调用opencv库 #include <opencv2/imgproc/imgproc.hpp> #include <cv_bridge/cv_bridge.h> //头文件cv_bridge中包含了CvBridge类,而CvBridge中的API可以将ROS下的sensor_msgs/Image消息类型转化成cv::Mat #include <iostream> #include <typeinfo> using namespace std; int main(int argc, char **argv) { ros::init(argc, argv, "hw_opencv"); ros::NodeHandle node; image_transport::ImageTransport transport(node); image_transport::Publisher image_pub = transport.advertise("OutImage", 1); cout << "\033[1;31m hw_opencv! \033[0m" << endl; cv::Mat cv_image = cv::imread("/home/djq/me.jpg"); if(cv_image.empty() ) { ROS_ERROR("Read the picture failed!"); return -1; } //将opencv格式的图像转化为ROS所支持的消息类型,从而发布到相应的话题上。 sensor_msgs::ImagePtr im_msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", cv_image).toImageMsg(); // sensor_msgs::Image im=*im_msg; // printf("%s\n",typeid(im_msg).name());//类型 // printf("%s\n",typeid(im).name());//类型 ros::Rate loop_rate(1); //发布图片消息 while (ros::ok()) { image_pub.publish(im_msg); ROS_INFO("Converted Successfully!"); ros::spinOnce(); loop_rate.sleep(); } return 0; }
-
结果
ps:查看图像也可以用这个指令rqt_image_view
4. 接收图像
-
代码
#include <ros/ros.h> #include <image_transport/image_transport.h> #include <opencv2/highgui/highgui.hpp> #include <cv_bridge/cv_bridge.h> #include <iostream> using namespace std; void imageCallback(const sensor_msgs::ImageConstPtr& msg) { cout << "\033[1;32m go! \033[0m" << endl; try { // 用于将ROS图像消息转化为Opencv支持的图像格式(采用BGR8编码方式) 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 node; cout << "\033[1;31m hw_opencv! \033[0m" << endl; cv::namedWindow("view"); cv::startWindowThread(); image_transport::ImageTransport transport(node); image_transport::Subscriber sub = transport.subscribe("OutImage", 1, imageCallback); ros::spin(); cv::destroyWindow("view"); }
-
效果
使用rosnode list
查看当前所有的node
使用rosrun rqt_graph rqt_graph
,查看