Robotics StackExchange | Archived questions

How to improve camera Fps

Hi ,

I'm trying to stream video from raspberry pi 4 with usb camera to an Ubuntu laptop.

I write publisher node to get video from cv2.VideoCapture() then publish frame by frame via topic, then I write subscriber node to get image from topic then display to screen.

Results are okay, I got video in my laptop screen from camera, but framerates are awfully low like 1-2 fps.

I try some method like lower the resolutions or change the frame from BGR to GRAYSCALE, but I think its still doesn't quite right.

This is publisher code to rpi.

import rclpy
from rclpy.qos import qos_profile_sensor_data
from rclpy.node import Node
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class ImagePublisher(Node):
    def __init__(self):
        super().__init__("webcam_pub")
        self.bridge = CvBridge()
        self.cap = cv2.VideoCapture(0, cv2.CAP_V4L)
        self.cap.set(3,192)
        self.cap.set(4,144)
        self.pub = self.create_publisher(Image, "/video_stream", qos_profile_sensor_data)
        # self.rgb8pub = self.create_publisher(Image, "/image/rgb", 10)
        # self.bgr8pub = self.create_publisher(Image, "/image/bgr", 10)
        # self.mono8pub = self.create_publisher(Image, "/image/mono", 10)

    def run(self):
        while True:
            try:
                r, frame = self.cap.read()
                tframe = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                if not r:
                    return
                self.pub.publish(self.bridge.cv2_to_imgmsg(tframe, "mono8"))

                # # BGR8
                # self.bgr8pub.publish(self.bridge.cv2_to_imgmsg(frame, "bgr8"))

                # # RGB8
                # frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                # self.rgb8pub.publish(self.bridge.cv2_to_imgmsg(frame_rgb, "rgb8"))

                # # MONO8
                # frame_mono = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                #self.pub.publish(self.bridge.cv2_to_imgmsg(frame, "mono8"))

            except CvBridgeError as e:
                print(e)
        self.cap.release()

def main(args=None):
    rclpy.init(args=args)

    ip = ImagePublisher()
    print("Publishing...")
    ip.run()

    ip.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

subscriber node to laptop

import rclpy
from rclpy.qos import qos_profile_sensor_data
from rclpy.node import Node
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class ImageSubscriber(Node):
    def __init__(self):
        super().__init__("webcam_sub")
        self.bridge = CvBridge()
        self.sub = self.create_subscription(Image, "/video_stream", self.image_callback , qos_profile_sensor_data)

    def image_callback(self, msg):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, 'mono8')
            cv_image = cv2.cvtColor(cv_image, cv2.COLOR_GRAY2BGR)
            cv2.imshow('Webcam Stream', cv_image)
            cv2.waitKey(1)
        except Exception as e:
            self.get_logger().error('cv_bridge exception: %s' % e)


def main(args=None):
    rclpy.init(args=args)

    ip = ImageSubscriber()
    print("Subscribing...")
    rclpy.spin(ip)

    ip.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

All running Ubuntu 22.04 with Ros2 humble.

Any improvement or alternative way? Thanks.

Asked by dandog on 2023-07-07 14:58:51 UTC

Comments

There are easily hundreds (maybe thousands?) of questions on this web site discussing how to publish images/video, so doing a search for the terms like "camera" or "cvbridge" or "video" or "gstreamer" should give you a lot of hits. Also, I would expect 99% of the ros1 advice to be valid for ros2.

Asked by Mike Scheutzow on 2023-07-08 06:37:56 UTC

Answers