ROS关于cv_brige的使用

本文涉及的产品
资源编排,不限时长
简介: 最近想使用OpenCV 和ROS实现点云的拼接,实现三维重建,那么在学习了kinect的基本的使用方法以后我们知道,直接使用ROS 的包即可得到点云,深度图,rgb图等信息,roslaunch openni_launch openni.launch(深度图彩色图,还有点云都获取了)rosrun openni_camera openni_node   (深度图与彩色图)那么实现点云的拼接就需要使用cv_bridge把ROS 的数据格式转为Opencv可以使用的数据格式。

最近想使用OpenCV 和ROS实现点云的拼接,实现三维重建,那么在学习了kinect的基本的使用方法以后我们知道,直接使用ROS 的包即可得到点云,深度图,rgb图等信息,

roslaunch openni_launch openni.launch(深度图彩色图,还有点云都获取了)

rosrun openni_camera openni_node   (深度图与彩色图)

那么实现点云的拼接就需要使用cv_bridge把ROS 的数据格式转为Opencv可以使用的数据格式。即是一个提供ROS和OpenCV库提供之间的接口的开发包。

                                                   

(1) 将ROS图像信息转换为OpenCV图像

cvbridge定义了一个opencv图像cvimage的类型、包含了编码和ROS的信息头。cvimage包含准确的信息sensor_msgs /image,因此我们可以将两种数据类型进行转换。cvimage类格式:

namespace cv_bridge {

class CvImage
{
public:
  std_msgs::Header header;
  std::string encoding;
  cv::Mat image;
};

typedef boost::shared_ptr<CvImage> CvImagePtr;
typedef boost::shared_ptr<CvImage const> CvImageConstPtr;

}

当要把一个ROS 的sensor_msgs /image 信息转化为一cvimage,cvbridge有两个不同的使用情况:

(1)如果要修改某一位的数据。我们必须复制ROS信息数据的作为副本。

(2)不修改数据。可以安全地共享的ROS信息,而不是复制的数据。

cvbridge转换为CvImage提供了以下功能:

// Case 1: Always copy, returning a mutable CvImage
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr& source,
                    const std::string& encoding = std::string());
CvImagePtr toCvCopy(const sensor_msgs::Image& source,
                    const std::string& encoding = std::string());

// Case 2: Share if possible, returning a const CvImage
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr& source,
                          const std::string& encoding = std::string());
CvImageConstPtr toCvShare(const sensor_msgs::Image& source,
                          const boost::shared_ptr<void const>& tracked_object,
                          const std::string& encoding = std::string());

输入是图像消息指针,以及可选的编码参数。编码是指cvimage的类型。

tocvcopy复制从ROS消息的图像数据,可以自由修改返回的cvimage。即使当源和目的编码匹配。

tocvshare将避免复制,在ROS的消息数据把指针返回的 cv::mat,,如果源和目的编码匹配。只要你保持一份返回的cvimage,ROS的消息数据将不会释放。如果编码不匹配时,它将分配一个新的缓冲区,执行转换。将不得修改返回的cvimage,因为它可能与ROS的图像信息共享数据,这反过来又可能与其他回调函数共享。注:对tocvshare二次过载更方便,转换当一个指针指向其他信息类型(如stereo_msgs / disparityimage)包含一个sensor_msgs /image。

如果没有编码(或更确切地说,空字符串),则目标图像编码将与图像消息编码相同。在这种情况下tocvshare保证不复制图像数据。图像编码可以是以下任何一个opencv图像编码:

  • 8UC[1-4]
  • 8SC[1-4]
  • 16UC[1-4]
  • 16SC[1-4]
  • 32SC[1-4]
  • 32FC[1-4]
  • 64FC[1-4]

介绍集中cvbridge 中常见的数据编码的形式,cv_bridge可以有选择的对颜色和深度信息进行转化。为了使用指定的特征编码,就有下面集中的编码形式:

mono8:  CV_8UC1, 灰度图像

mono16: CV_16UC1,16位灰度图像

bgr8: CV_8UC3,带有颜色信息并且颜色的顺序是BGR顺序

rgb8: CV_8UC3,带有颜色信息并且颜色的顺序是RGB顺序

bgra8: CV_8UC4, BGR的彩色图像,并且带alpha通道

rgba8: CV_8UC4,CV,RGB彩色图像,并且带alpha通道

注:这其中mono8和bgr8两种图像编码格式是大多数OpenCV的编码格式。

Finally, CvBridge will recognize Bayer pattern encodings as having OpenCV type 8UC1 (8-bit unsigned, one channel). It will not perform conversions to or from Bayer pattern; in a typical ROS system, this is done instead by image_proc. CvBridge recognizes the following Bayer encodings:

  • bayer_rggb8

  • bayer_bggr8

  • bayer_gbrg8

  • bayer_grbg8

1.把Opencv图像转换为ROS图像格式

To convert a CvImage into a ROS image message, use one the toImageMsg() member function:

class CvImage
{
  sensor_msgs::ImagePtr toImageMsg() const;

  // Overload mainly intended for aggregate messages that contain
  // a sensor_msgs::Image as a member.
  void toImageMsg(sensor_msgs::Image& ros_image) const;
};

举个例子

首先要在创建的包CMakeLists.txt里添加依赖包。分别如下:

sensor_msgs
cv_bridge
roscpp
std_msgs
image_transport                         

 在src文件下建立一个cv_ros_beginner.cpp文件文件内容如下

#include <ros/ros.h>               //ros 的头文件
#include <image_transport/image_transport.h>   //image_transport
#include <cv_bridge/cv_bridge.h>              //cv_bridge
#include <sensor_msgs/image_encodings.h>    //图像编码格式
#include <opencv2/imgproc/imgproc.hpp>      //图像处理
#include <opencv2/highgui/highgui.hpp>       //opencv GUI

static const std::string OPENCV_WINDOW = "Image window";   //申明一个GUI 的显示的字符串

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("/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;  //申明一个CvImagePtr
    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;
    }
//转化为opencv的格式之后就可以对图像进行操作了
    // Draw an 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, "image_converter");
  ImageConverter ic;
  ros::spin();
  return 0;
}

然后在CMakeLists.txt添加,

  add_executable(cv_ros_beginner src/cv_ros_beginner.cpp)
 target_link_libraries(cv_ros_beginner
   ${catkin_LIBRARIES}
 )

返回catin_ws 下catkin_make即可生成可执行文件

那么我们在查看结果的时候就是要把

image_sub_ = it_.subscribe("/rgb/image_raw", 1, &ImageConverter::imageCb, this);                 

把订阅的节点换成之前我们需要订阅的节点即可实现    在订阅的图像上画一个小圆圈,并且可视化出来。

 (小技巧记录:如果你的工作空间下包很多,每次都使用catkin_make的话效率十分低下,因为这种编译方法会编译工作空间下的所有的包,特别是我们在调试程序是会经常修改CMakeLists.txt文件里的内容,这样每次都会要编译整个工作空间,那么所以我们可以使用ROS的catkin_Make的功能编译一个或者多个包,具体的命令是:catkin_make -DCATKIN_WHITELIST_PACKAGES=" 你的包名"),例如:catkin_make -DCATKIN_WHITELIST_PACKAGES="ros_slam"

如果需要编译两个或者多个只需要中间加分号即可catkin_make -DCATKIN_WHITELIST_PACKAGES="ros_slam;cv_bridge",

只是搬运以下官网的程序,当然你可以实现更多的处理

那么有关于ROS以及PCL的使用的兴趣者扫描二维码关注一起与我交流分享

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
相关文章
|
计算机视觉 C++
OpenCV-计时函数cv::getTickCount&cv::getTickFrequency
OpenCV-计时函数cv::getTickCount&cv::getTickFrequency
173 0
|
1月前
|
算法 计算机视觉
Opencv学习笔记(六):cv2.resize函数的介绍
这篇文章介绍了OpenCV库中cv2.resize函数的使用方法,包括其参数、插值方式选择以及实际代码示例。
294 1
Opencv学习笔记(六):cv2.resize函数的介绍
|
1月前
|
计算机视觉
Opencv学习笔记(五):cv2.putText()和cv2.rectangle()详细理解
这篇文章详细介绍了OpenCV库中的`cv2.putText()`和`cv2.rectangle()`函数的使用方法,并通过一个实战例子展示了如何使用这些函数在图像上绘制文字和矩形框。
146 0
Opencv学习笔记(五):cv2.putText()和cv2.rectangle()详细理解
|
3月前
|
存储 计算机视觉
OpenCV 中 CV_8UC1,CV_32FC3,CV_32S等参数的含义
OpenCV 中 CV_8UC1,CV_32FC3,CV_32S等参数的含义
208 3
|
算法 机器人 API
【ROS】TF2坐标转换及实战示例
ROS中提供了坐标转换的软件包 Transform Frame TF的作用是ROS中实现不同坐标点/向量的转换。
693 0
|
机器人 API
[ROS基础] --- TF坐标转换
[ROS基础] --- TF坐标转换
195 0
|
C++
ROS学习-写一个tf broadcaster(C++)
ROS学习-写一个tf broadcaster(C++)
185 0
ROS学习-写一个tf broadcaster(C++)
|
数据可视化 Ubuntu 机器人
ROS学习-tf介绍
ROS学习-tf介绍
262 0
ROS学习-tf介绍
|
数据可视化 机器人 C++
ROS TF2
turtlesim的多机器人示例中,展示了tf2的一些功能。 也介绍了使用tf2_echo,view_frames和rviz。 使对tf2可以做的事情有个很好的了解。
ROS TF2
|
计算机视觉
安装 opencv 之后 cv2 无法使用
安装 opencv 之后 cv2 无法使用
173 0