Repository Summary

Description ROS 2 tutorials for image_transport.
Checkout URI https://github.com/ros-perception/image_transport_tutorials.git
VCS Type git
VCS Version main
Last Updated 2025-05-23
Dev Status UNKNOWN
Released UNRELEASED
Tags No category tags.
Contributing Help Wanted (-)
Good First Issues (-)
Pull Requests to Review (-)

Packages

README

image_transport_tutorials

Table of Contents

  1. Installation
  2. Writing a Simple Image Publisher (C++)
  3. Writing a Simple Image Subscriber (C++)
  4. Running the Simple Image Publisher and Subscriber with Different Transport
  5. Writing a Simple Image Publisher (Python)
  6. Writing a Simple Image Subscriber (Python)

Installation

Before starting any of the tutorials below, create a workspace and clone this repository so you can inspect and manipulate the code:

$ mkdir -p ~/image_transport_tutorials_ws/src
$ cd ~/image_transport_tutorials_ws/src
$ git clone https://github.com/ros-perception/image_transport_tutorials.git

Install needed dependencies:

$ cd ~/image_transport_tutorials_ws/
$ source /opt/ros/iron/setup.bash
$ rosdep install -i --from-path src --rosdistro iron -y
$ colcon build

Make sure to include the correct setup file (in the above example it is for Iron on Ubuntu and for bash).

Writing a Simple Image Publisher (C++)

Description: This tutorial shows how to create a publisher node that will continually publish an image.

Tutorial Level: Beginner

Take a look at my_publisher.cpp.

The code explained

Now, let’s break down the code piece by piece. For lines not explained here, review Writing a Simple Publisher and Subscriber (C++).

#include "cv_bridge/cv_bridge.h"
#include "image_transport/image_transport.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "rclcpp/rclcpp.hpp"

These headers will allow us to load an image using OpenCV, convert it to the ROS message format, and publish it.

rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("image_publisher", options);
image_transport::ImageTransport it(node);

We create an ImageTransport instance, initializing it with our node. We use methods of ImageTransport to create image publishers and subscribers, much as we use methods of Node to create generic ROS publishers and subscribers.

image_transport::Publisher pub = it.advertise("camera/image", 1);

Advertise that we are going to be publishing images on the base topic camera/image. Depending on whether more plugins are built, additional (per-plugin) topics derived from the base topic may also be advertised. The second argument is the size of our publishing queue.

advertise() returns an image_transport::Publisher object, which serves two purposes:

  1. It contains a publish() method that lets you publish images onto the base topic it was created with
  2. When it goes out of scope, it will automatically unadvertise
cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR);
std_msgs::msg::Header hdr;
sensor_msgs::msg::Image::SharedPtr msg;
msg = cv_bridge::CvImage(hdr, "bgr8", image).toImageMsg();

We load a user-specified (on the command line) color image from disk using OpenCV, then convert it to the ROS type sensor_msgs/msg/Image.

rclcpp::WallRate loop_rate(5);
while (rclcpp::ok()) {
  pub.publish(msg);
  rclcpp::spin_some(node);
  loop_rate.sleep();
}

We broadcast the image to anyone connected to one of our topics, exactly as we would have using an rclcpp::Publisher.

Adding video stream from a webcam

The example above requires a path to an image file to be added as a command line parameter. This image will be converted and sent as a message to an image subscriber. In most cases, however, this is not a very practical example as you are often required to handle streaming data. (For example: multiple webcams mounted on a robot record the scene around it and you have to pass the image data to some other node for further analysis).

The publisher example can be modified quite easily to make it work with a video device supported by cv::VideoCapture (in case it is not, you have to handle it accordingly). Take a look at publisher_from_video.cpp to see how a video device can be passed in as a command line argument and used as the image source.

File truncated at 100 lines see the full file

CONTRIBUTING

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that license:

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

Contributors must sign-off each commit by adding a Signed-off-by: ... line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the Developer Certificate of Origin (DCO).

Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): ~~~ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. ~~~ Contributors must sign-off each commit by adding a `Signed-off-by: ...` line to commit messages to certify that they have the right to submit the code they are contributing to the project according to the [Developer Certificate of Origin (DCO)](https://developercertificate.org/).