需求:从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());
}
}
人言是牡丹,佛说是花箭。射人入骨髓,死而不知怨。