How to improve camera Fps

asked 2023-07-07 14:58:51 -0500

dandog gravatar image

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.

edit retag flag offensive close merge delete

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.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2023-07-08 06:37:56 -0500 )edit