创建包:

ros2 pkg create opencv_demo --build-type ament_cmake --dependencies rclcpp sensor_msgs OpenCV cv_bridge image_transport --node-name opencv_base

1.OpenCV图像读取与显示

OpenCV读取本地图片并显示。

#include <cstdio>
#include <opencv2/opencv.hpp>

int main(int argc, char ** argv)
{
  (void) argc;
  (void) argv;
  // 读取图片
  cv::Mat pic = cv::imread("/home/ros2u/map.jpg");  //请自行修改图片路径
  // 显示图片
  cv::imshow("my_pic", pic);
  // 使显示窗口一直处于打开状态
  cv::waitKey(0);               

  return 0;
}

Python

import cv2

def main(args=None):
    # 读取图片
    pic = cv2.imread("/home/ros2u/map.jpg")  #请自行修改图片路径
    # 显示图片
    cv2.imshow("my_pic", pic)
    # 使显示窗口一直处于打开状态
    cv2.waitKey(0)


if __name__ == '__main__':
    main()

2.OpenCV转ROS2

/*
    需求:读取本地图片,并使用ROS2进行发布。
    流程:
        1.包含头文件;
        2.初始化ROS2客户端;
        3.自定义节点类;
          3-1.读取图片资源;
          3-2.创建图片发布方;
          3-3.创建定时器,在定时器回调函数中实现图片转换以及发布。
        4.调用spin函数,并传入节点对象指针;
        5.资源释放。
*/
// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "opencv2/opencv.hpp"
#include "sensor_msgs/msg/image.hpp"
#include "cv_bridge/cv_bridge.h"

using namespace std::chrono_literals;

// 3.自定义节点类;
class OpencvRos2: public rclcpp::Node{
public:
    OpencvRos2():Node("opencv_ros2_node_cpp"){
      // 读取图片
      pic = cv::imread("/home/ros2u/map.jpg");  //请自行修改图片路径
      // 图片发布方
      img_pub = this->create_publisher<sensor_msgs::msg::Image>("image_raw",10);
      // 定时器
      timer = this->create_wall_timer(0.1s,std::bind(&OpencvRos2::cb,this));
    }
private:
    rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr img_pub;
    rclcpp::TimerBase::SharedPtr timer;
    cv::Mat pic;
    void cb(){
      // 转换成ROS2的图片消息
      auto ros_image = cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", pic).toImageMsg();
      ros_image->header.frame_id="camera";
      ros_image->header.stamp = this->now();
      // 发布图片
      img_pub->publish(*ros_image);

    }
};

int main(int argc, char const *argv[])
{
    // 2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    // 4.调用spain函数,并传入节点对象指针;
    rclcpp::spin(std::make_shared<OpencvRos2>());
    // 5.资源释放。
    rclcpp::shutdown();
    return 0;
}

python

import cv2
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from std_msgs.msg import Header
import pathlib
import os

class OpencvRos2(Node):

    def __init__(self):
        super().__init__('opencv_ros2_node_py')


        # 读取图片
        home_path = str(pathlib.Path.home())
        pic_path = os.path.join(home_path, "map.jpg") # 请自行修改图片路径
        self.pic = cv2.imread(pic_path)

        # 图片发布方
        self.img_pub = self.create_publisher(Image, 'image_raw', 10)

        # 定时器
        timer_period = 0.1  # seconds
        self.timer = self.create_timer(timer_period, self.cb)

        # 创建CvBridge对象
        self.bridge = CvBridge()

    def cb(self):
        # 转换成ROS2的图片消息
        ros_image = self.bridge.cv2_to_imgmsg(self.pic, encoding='bgr8')
        ros_image.header.frame_id = 'camera'
        ros_image.header.stamp = self.get_clock().now().to_msg()

        # 发布图片
        self.img_pub.publish(ros_image)


def main(args=None):
    # 初始化ROS2客户端
    rclpy.init(args=args)
    # 创建节点对象
    opencv_ros2_node = OpencvRos2()
    # 调用spin函数
    rclpy.spin(opencv_ros2_node)
    # 节点销毁与资源释放
    opencv_ros2_node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

3.ROS2转OpenCV

/*
    需求:
    流程:
        1.包含头文件;
        2.初始化ROS2客户端;
        3.自定义节点类;

        4.调用spin函数,并传入节点对象指针;
        5.资源释放。
*/
// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "opencv2/opencv.hpp"
#include "cv_bridge/cv_bridge.h"
#include "sensor_msgs/msg/image.hpp"


using namespace std::placeholders;
// 3.自定义节点类;
class Ros2Opencv: public rclcpp::Node{
public:
    Ros2Opencv():Node("ros2_opencv_node_cpp"){

        image_sub = this->create_subscription<sensor_msgs::msg::Image>("/image",10,std::bind(&Ros2Opencv::cb,this,_1));

    }

private:
    rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr image_sub;
    void cb(const sensor_msgs::msg::Image & image){
      try
      {
        // RCLCPP_INFO(this->get_logger(),"-----");
        auto cv_img_ptr = cv_bridge::toCvCopy(image,sensor_msgs::image_encodings::BGR8);
        cv::Mat mat = cv_img_ptr->image;
        // 在 OpenCV 窗口中显示图像
        cv::imshow("ROS2 image", mat);
        cv::waitKey(1);
      }
      catch(cv_bridge::Exception& e)
      {
        RCLCPP_INFO(this->get_logger(),"error:%s",e.what());
      }



    }
};

int main(int argc, char const *argv[])
{
    // 2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    // 4.调用spain函数,并传入节点对象指针;
    rclcpp::spin(std::make_shared<Ros2Opencv>());
    // 5.资源释放。
    rclcpp::shutdown();
    return 0;
}

Python

# 1. 导入模块;
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2


# 3. 自定义节点类;
class Ros2Opencv(Node):
    def __init__(self):
        super().__init__('ros2_opencv_node_py')
        self.image_sub = self.create_subscription(
            Image,
            '/image',
            self.cb,
            10)
        self.cv_bridge = CvBridge()


    def cb(self, image_msg):
        try:
            # 将 ROS 图像消息转换为 OpenCV 图像格式
            cv_img = self.cv_bridge.imgmsg_to_cv2(image_msg, 'bgr8')
            # 在 OpenCV 窗口中显示图像
            cv2.imshow('ROS2 image', cv_img)
            cv2.waitKey(1)

        except Exception as e:
            self.get_logger().info('Error: %s' % str(e))


def main(args=None):
    # 2. 初始化 ROS2 客户端;
    rclpy.init(args=args)

    # 创建节点对象;
    ros2_opencv = Ros2Opencv()

    # 4. 调用 spin 函数,并传入节点对象;
    rclpy.spin(ros2_opencv)

    # 5. 资源释放。
    ros2_opencv.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

results matching ""

    No results matching ""