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

约定不等于承诺〃 2023-10-13 09:16 133阅读 0赞

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

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

  1. // 初始化ros节点
  2. ros::init(argc, argv, "RGBD");
  3. // 创建ros节点句柄
  4. ros::NodeHandle nh;
  5. image_transport::ImageTransport it(nh);
  6. // 回调函数队列长度为x,因此spinOnce每次执行完队列函数,相当于每x帧取1帧
  7. image_transport::Subscriber rgb_sub = it.subscribe("rgb", 1, rgbCallback);
  8. 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。可以理解为浅拷贝。

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

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

  1. cv::Mat rgb;
  2. cv::Mat depth;
  3. // rgb图像的回调函数,当有图像消息到达rgb时,就会被调用
  4. void rgbCallback(const sensor_msgs::ImageConstPtr& msg) {
  5. try {
  6. // ROS图像消息——>OpenCV图像
  7. rgb = cv_bridge::toCvShare(msg, "bgr8")->image;
  8. // cv::imshow("image", rgb);
  9. // cv::waitKey(50);
  10. // cout << "I have received rgb image!" << endl;
  11. // rgb = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;
  12. } catch(cv_bridge::Exception& e) {
  13. ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
  14. }
  15. }
  16. // depth深度图像的回调函数
  17. void depthCallback(const sensor_msgs::ImageConstPtr& msg) {
  18. try {
  19. // ROS图像消息——>OpenCV图像
  20. depth = cv_bridge::toCvShare(msg, "mono16")->image;
  21. // cout << "I have received depth image!" << endl;
  22. } catch(cv_bridge::Exception& e) {
  23. ROS_ERROR("Could not convert from '%s' to 'mono16'.", msg->encoding.c_str());
  24. }
  25. }

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

发表评论

表情:
评论列表 (有 0 条评论,133人围观)

还没有评论,来说两句吧...

相关阅读