Complete code

#!/usr/bin/env python3

import os
import rospy
import cv2
import rosbag

from sensor_msgs.msg import Image
from cv_bridge import CvBridge

bag_name = '../2023-04-14-11-57-21.bag'

bag = rosbag.Bag(bag_name, "r")
bridge = CvBridge()
count = 0

image_topic = '/zed2/zed_node/left/image_rect_color'#'/zed2/zed_node/left/image_rect_color'
output_dir = '../Images/'
every = 2

for topic, msg, t in bag.read_messages(topics=image_topic):

    if count%every == 0:
        cv_img = bridge.imgmsg_to_cv2(msg, desired_encoding="passthrough")
        name = output_dir+str(count)+'2.png'
        cv2.imwrite( name, cv_img)
        print ("Wrote image %i" % count)
        
    count += 1

bag.close()

Breakdown

  1. define which python to use for ROS
#!/usr/bin/env python3
  1. import all libraries rospy connects python to ROS. rosbag for reading from bagfiles
import os
import rospy
import cv2
import rosbag
  1. path to bagfile bag_name
bag_name = '../2023-04-14-11-57-21.bag'
  1. read bagfile bag = rosbag.Bag(bag_name, "r")
  2. CvBrdige for converting ros message Image to OpenCV image type for handling bridge = CvBridge()
  3. initialize the count count = 0
  4. define image topic, image_topic = '/zed2/zed_node/left/image_rect_color'
  5. path to save output images output_dir = '../Images/'
  6. save every 2nd frame every = 2
  7. Loop through the complete bagfile going trough all the message, for topic, msg, t in bag.read_messages(topics=image_topic):
  8. if count is divisble by every i.e. when it reaches every n^th frame: if count%every == 0:
    1. change ros image to openCV image : cv_img = bridge.imgmsg_to_cv2(msg, desired_encoding="passthrough")
    2. define name for saving image name = output_dir+str(count)+'2.png'
    3. save the image cv2.imwrite( name, cv_img)
  9. increase the count every time it passes through loop : count+=1
  10. close the bagfile bag.close