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.
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.