ROS订阅Image话题,转换为OpenCV图像

需求:从realsense相机发布的话题中拿到rgb图像和depth图像,并进行后续处理。ROS中提供了cv_bridge类帮助我们在ROS和OpenCV图像格式间转换。

订阅方需要用image_transport定义一个对象it,然后定义两个Subscriber对象,分别用来回调rgb和depth话题。

	// 初始化ros节点
    ros::init(argc, argv, "RGBD");
    // 创建ros节点句柄
    ros::NodeHandle nh;
    image_transport::ImageTransport it(nh);
    // 回调函数队列长度为x,因此spinOnce每次执行完队列函数,相当于每x帧取1帧
    image_transport::Subscriber rgb_sub = it.subscribe("rgb", 1, rgbCallback);
    image_transport::Subscriber depth_sub = it.subscribe("depth", 1, depthCallback);

当cv_bridge将ROS的图像消息转换为OpenCV图像格式时都是通过CvImage类实现的。一般来说,cv_bridge提供了两种方式转换为CvImage类,分别为复制(copy)和共享(share)。

  • toCvCopy函数会从ROS消息中拷贝一个图像数据,不管如何修改CvImage类的内容都不会影响源数据
  • toCvShare函数则是在源和编码都匹配的情况下将返回的OpenCV指针指向ROS的消息,即共享指针。它的特点是只要你还保持着返回的CvImage类的副本,那么ROS的消息类型就不会被释放。

CvBridge中常用的编码有以下几种:

  • mono8: CV_8UC1, grayscale image

  • mono16: CV_16UC1, 16-bit grayscale image

  • bgr8: CV_8UC3, color image with blue-green-red color order

  • rgb8: CV_8UC3, color image with red-green-blue color order

  • bgra8: CV_8UC4, BGR color image with an alpha channel

  • rgba8: CV_8UC4, RGB color image with an alpha channel

cv_bridge::toCvShare(msg, "bgr8")是将msg转换为 CV_8UC3 的图像,然后得到指向msg的共享指针,->image就是取得图像,格式为cv::Mat。可以理解为浅拷贝。

rgb = cv_bridge::toCvShare(msg, "bgr8")->image;

cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)也是将msg转换为 CV_8UC3 的图像,但是它只指向转换后的图像,格式为cv::Mat。可以理解为深拷贝。

cv::Mat rgb;
cv::Mat depth;

// rgb图像的回调函数,当有图像消息到达rgb时,就会被调用
void rgbCallback(const sensor_msgs::ImageConstPtr& msg) {
    try {           
        // ROS图像消息——>OpenCV图像
        rgb = cv_bridge::toCvShare(msg, "bgr8")->image;
        // cv::imshow("image", rgb);
        // cv::waitKey(50);
        // cout << "I have received rgb image!" << endl;
        // rgb = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;
        
    } catch(cv_bridge::Exception& e) {
        ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
    }
}

// depth深度图像的回调函数
void depthCallback(const sensor_msgs::ImageConstPtr& msg) {
    try {           
        // ROS图像消息——>OpenCV图像
        depth = cv_bridge::toCvShare(msg, "mono16")->image;
        // cout << "I have received depth image!" << endl;
    } catch(cv_bridge::Exception& e) {
        ROS_ERROR("Could not convert from '%s' to 'mono16'.", msg->encoding.c_str());
    }
}

人言是牡丹,佛说是花箭。射人入骨髓,死而不知怨。

你可能感兴趣的:(ROS,opencv,人工智能,计算机视觉,ros,机器人,话题通信)