I don’t know why this is not documented better but…

While I was porting my old ROS2 Python test application to the newest ROS2 Foxy on my Raspberry Pi’s, I discovered that I needed to use OpenCV to capture images because picamera does not work in 64 bit](https://github.com/waveform80/picamera/issues/540) .

What’s not documented very well (and I spent several days figuring out) is that, after one has ported to OpenCV, converting an OpenCV image into a ROS2 message is not obvious. After a bunch of Google’ing, one discovers that the ROS2 folks have packaged all the magic into a module called CvBridge.

OpenCV keeps images in cv:im structures and converting that into a byte array that fits into the ROS2 message is tricky. Actually, what’s expected in a ROS2 image message is not documented very well so what works is hard to figure out in the first place.

The ROS2 developers have created some tools for the OpenCV users and one is a tool that converts OpenCV images into ROS2 image messages. So, the code ends up looking like:

from sensor_msgs.msg import Image
import cv2
from cv_bridge import CvBridge
...
self.bridge = CvBridge()
self.camera = cv2.VideoCapture(0)
self.frame_num = 0
self.publisher = self.create_publisher(Image, "topic", 10)
...
ret, frame = self.camera.read()
if ret == True:
    msg = self.bridge.cv2_to_imgmsg(frame, 'bgr8')
    msg.header.frame_id = str(self.frame_num)   # 'msg' is a ROS2 sensor_msgs/Image.msg
    self.frame_num += 1
    self.publisher.publish(msg)

That is, don’t try to create the image message yourself. Instead, rely on the CvBridge package to create the whole message and then fill it in with other information.