How to subscribe and publish images in ROS

Question:

I am trying to subscribe to the “/camera/image_color” topic which is data from my camera. I then want to do some voodoo on these images in opencv and publish them at a specific frequency. So that I can subscribe to them with another node.

I have sofar tried the below code, and many many variations thereof. At this point the code is doing nothing. No images are being published to the “/imagetimer” topic. I get an output “Timing images” then nothing happens further.

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
import os
import numpy as np


class Nodo(object):
    def __init__(self):
        # Params
        self.image = None
        self.br = CvBridge()
        # Node cycle rate (in Hz).
        self.loop_rate = rospy.Rate(1)

        # Publishers
        self.pub = rospy.Publisher('imagetimer', Image,queue_size=10)

        # Subscribers
        rospy.Subscriber("/camera/image_color",Image,self.callback)


    def callback(self, msg):
        self.image = self.br.imgmsg_to_cv2(msg)


    def start(self):
        rospy.loginfo("Timing images")
        rospy.spin()
        br = CvBridge()
        while not rospy.is_shutdown():
            rospy.loginfo('publishing image')
            #br = CvBridge()
            self.pub.publish(br.cv2_to_imgmsg(self.image))
            rate.sleep()

if __name__ == '__main__':
    rospy.init_node("imagetimer111", anonymous=True)
    my_node = Nodo()
    my_node.start()

Asked By: Ian

||

Answers:

In my case, I found that the image topic had compressed images. Please verify if that is the case for you.

I used the following code to read from .bag files. If you find that you have compressed images coming in on your ROS topic, you can use parts of this code to perform the conversion

        bag = rosbag.Bag(os.path.join(path_to_bags, bag_list[index]))
        for topic, msg, t in bag.read_messages(topics=['/conti115/image_raw/compressed']):
            try:
                img = bridge.compressed_imgmsg_to_cv2(msg)
            except CvBridgeError, e:
                print e
            txt = str(datetime.datetime.fromtimestamp(t.to_sec()))
            cv2.rectangle(img, (0, 0), (500, 40), (0,0,0), -1)
            cv2.putText(img, txt, (0, 30), 1, 2, (255, 255, 255), 2)
            cv2.imshow("win",img)


            wtr.write(img)
            if cv2.waitKey(5)==27:
                cv2.destroyAllWindows()
                break
        bag.close()
Answered By: Shawn Mathew

Once you run rospy.spin() the code doesn’t go forward. In rospy as soon as you have the rospy.Subsriber() line it spins off another thread for the callback. A rospy.spin() essentially keeps the node alive so the callbacks and keep chugging.
Here you are using a while loop for keeping the node alive, so shouldn’t need rospy.spin().
This version should work:

import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
import os
import numpy as np

class Nodo(object):
    def __init__(self):
        # Params
        self.image = None
        self.br = CvBridge()
        # Node cycle rate (in Hz).
        self.loop_rate = rospy.Rate(1)

        # Publishers
        self.pub = rospy.Publisher('imagetimer', Image,queue_size=10)

        # Subscribers
        rospy.Subscriber("/camera/image_color",Image,self.callback)

    def callback(self, msg):
        rospy.loginfo('Image received...')
        self.image = self.br.imgmsg_to_cv2(msg)


    def start(self):
        rospy.loginfo("Timing images")
        #rospy.spin()
        while not rospy.is_shutdown():
            rospy.loginfo('publishing image')
            #br = CvBridge()
            if self.image is not None:
                self.pub.publish(self.br.cv2_to_imgmsg(self.image))
            self.loop_rate.sleep()
            
if __name__ == '__main__':
    rospy.init_node("imagetimer111", anonymous=True)
    my_node = Nodo()
    my_node.start()
Answered By: Vik
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.