一、cv_bridge cv_bridge是将ROS中的图像信息转化为OpenCV的图像信息,从而使用OpenCV进行图像处理。 二、创建功能包
$ catkin_create_pkg ros_bridge_opencv cv_bridge image_transport roscpp sensor_msgs std_msgs rospy三、配置CMakeList.txt文件
# 寻找OpenCV库 find_package(OpenCV REQUIRED) # 添加头文件 include_directories(${OpenCV_INCLUDE_DIRS}) # 生成编译文件 add_executable(bridge src/bridge.cpp) #链接OpenCV库 target_link_libraries(bridge ${OpenCV_LIBS})四、在src中创建bridge.cpp
#include <ros/ros.h> // 用image_transport软件包发布和订阅ROS中的图像 #include <image_transport/image_transport.h> // 这两个头文件包含了CvBridge类以及与图像编码相关的函数 #include <cv_bridge/cv_bridge.h> #include <sensor_msgs/image_encodings.h> // 这两个头文件包含了OpenCV图像处理模块和GUI模块 #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> static const std::string OPENCV_WINDOW = "Image window"; class ImageConverter { ros::NodeHandle nh_; image_transport::ImageTransport it_; // 声明订阅者和发布者对象 image_transport::Subscriber image_sub_; image_transport::Publisher image_pub_; public: ImageConverter() : it_(nh_) { // Subscrive to input video feed and publish output video feed image_sub_ = it_.subscribe("/camera/rgb/image_raw", 1, &ImageConverter::imageCb, this); image_pub_ = it_.advertise("/image_converter/output_video", 1); cv::namedWindow(OPENCV_WINDOW); } ~ImageConverter() // 析构函数 { cv::destroyWindow(OPENCV_WINDOW); } void imageCb(const sensor_msgs::ImageConstPtr& msg) { cv_bridge::CvImagePtr cv_ptr; try { cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); } catch (cv_bridge::Exception& e) { ROS_ERROR("cv_bridge exception: %s", e.what()); return; } // Draw as example circle on the video stream if (cv_ptr->image.rows > 60 && cv_ptr->image.cols > 60) cv::circle(cv_ptr->image, cv::Point(50, 50), 10, CV_RGB(255, 0, 0)); // Update GUI Window cv::imshow(OPENCV_WINDOW, cv_ptr->image); cv::waitKey(3); // Output modified video stream image_pub_.publish(cv_ptr->toImageMsg()); } }; int main(int argc, char** argv) { ros::init(argc, argv, "birdge"); ImageConverter ic; ros::spin(); return 0; } # 打开相机 $ roslaunch astra_launch astra.launch # 在工作空间中编译 $ catkin_make $ sorce devel/setup.bash $ rosrun ros_bridge_opencv bridge五、在scripts中创建一个opencv_bridge_test.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import rospy import cv2 from cv_bridge import CvBridge, CvBridgeError from sensor_msgs.msg import Image class image_converter: def __init__(self): # 创建cv_bridge,声明图像的发布者和订阅者 self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1) self.bridge = CvBridge() self.image_sub = rospy.Subscriber("/camera/rgb/image_raw", Image, self.callback) def callback(self,data): # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式 try: cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8") except CvBridgeError as e: print e # 在opencv的显示窗口中绘制一个圆,作为标记 (rows,cols,channels) = cv_image.shape if cols > 60 and rows > 60 : cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1) # 显示Opencv格式的图像 cv2.imshow("Image window", cv_image) cv2.waitKey(3) # 再将opencv格式额数据转换成ros image格式的数据发布 try: self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8")) except CvBridgeError as e: bridge print e if __name__ == '__main__': try: # 初始化ros节点 rospy.init_node("opencv_bridge_test") rospy.loginfo("Starting cv_bridge_test node") image_converter() rospy.spin() except KeyboardInterrupt: print "Shutting down cv_bridge_test node." cv2.destroyAllWindows() # 打开相机 $ roslaunch astra_launch astra.launch # 在工作空间中编译 $ catkin_make $ sorce devel/setup.bash $ rosrun ros_bridge_opencv opencv_bridge_test.py在两种代码中订阅者的相机信息与驱动的相机有关,需要订阅自己相机信息的话题。
参考: 1、Converting between ROS images and OpenCV images (C++) 2、《ROS机器人开发实践》
总有一个遗忘的过程,记录一下为以后查找方便。