Skip to content

Instantly share code, notes, and snippets.

@Goddard
Forked from wngreene/publish_video.py
Created November 19, 2017 23:27
Show Gist options
  • Select an option

  • Save Goddard/f5ad1888f11f5f05c7421daccf3623e4 to your computer and use it in GitHub Desktop.

Select an option

Save Goddard/f5ad1888f11f5f05c7421daccf3623e4 to your computer and use it in GitHub Desktop.

Revisions

  1. @wngreene wngreene created this gist Aug 1, 2017.
    124 changes: 124 additions & 0 deletions publish_video.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,124 @@
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    # Copyright 2016 Massachusetts Institute of Technology

    """Publish a video as ROS messages.
    """

    import argparse

    import numpy as np

    import cv2

    import rospy

    from sensor_msgs.msg import Image
    from sensor_msgs.msg import CameraInfo

    import camera_info_manager

    from cv_bridge import CvBridge, CvBridgeError

    bridge = CvBridge()

    def main():
    """Publish a video as ROS messages.
    """
    # Patse arguments.
    parser = argparse.ArgumentParser(description="Convert video into a rosbag.")
    parser.add_argument("video_file", help="Input video.")
    parser.add_argument("-c", "--camera", default="camera", help="Camera name.")
    parser.add_argument("-f", "--frame_id", default="camera",
    help="tf frame_id.")
    parser.add_argument("--width", type=np.int32, default="640",
    help="Image width.")
    parser.add_argument("--height", type=np.int32, default="480",
    help="Image height.")
    parser.add_argument("--info_url", default="file:///camera.yml",
    help="Camera calibration url.")

    args = parser.parse_args()

    print "Publishing %s." % (args.video_file)

    # Set up node.
    rospy.init_node("video_publisher", anonymous=True)
    img_pub = rospy.Publisher("/" + args.camera + "/image_raw", Image,
    queue_size=10)
    info_pub = rospy.Publisher("/" + args.camera + "/camera_info", CameraInfo,
    queue_size=10)

    info_manager = camera_info_manager.CameraInfoManager(cname=args.camera,
    url=args.info_url,
    namespace=args.camera)
    info_manager.loadCameraInfo()

    # Open video.
    video = cv2.VideoCapture(args.video_file)

    # Get frame rate.
    fps = video.get(cv2.cv.CV_CAP_PROP_FPS)
    rate = rospy.Rate(fps)

    # Loop through video frames.
    while not rospy.is_shutdown() and video.grab():
    tmp, img = video.retrieve()

    if not tmp:
    print "Could not grab frame."
    break

    img_out = np.empty((args.height, args.width, img.shape[2]))

    # Compute input/output aspect ratios.
    aspect_ratio_in = np.float(img.shape[1]) / np.float(img.shape[0])
    aspect_ratio_out = np.float(args.width) / np.float(args.height)

    if aspect_ratio_in > aspect_ratio_out:
    # Output is narrower than input -> crop left/right.
    rsz_factor = np.float(args.height) / np.float(img.shape[0])
    img_rsz = cv2.resize(img, (0, 0), fx=rsz_factor, fy=rsz_factor,
    interpolation=cv2.INTER_AREA)

    diff = (img_rsz.shape[1] - args.width) / 2
    img_out = img_rsz[:, diff:-diff-1, :]
    elif aspect_ratio_in < aspect_ratio_out:
    # Output is wider than input -> crop top/bottom.
    rsz_factor = np.float(args.width) / np.float(img.shape[1])
    img_rsz = cv2.resize(img, (0, 0), fx=rsz_factor, fy=rsz_factor,
    interpolation=cv2.INTER_AREA)

    diff = (img_rsz.shape[0] - args.height) / 2

    img_out = img_rsz[diff:-diff-1, :, :]
    else:
    # Resize image.
    img_out = cv2.resize(img, (args.height, args.width))

    assert img_out.shape[0:2] == (args.height, args.width)

    try:
    # Publish image.
    img_msg = bridge.cv2_to_imgmsg(img_out, "bgr8")
    img_msg.header.stamp = rospy.Time.now()
    img_msg.header.frame_id = args.frame_id
    img_pub.publish(img_msg)

    # Publish camera info.
    info_msg = info_manager.getCameraInfo()
    info_msg.header = img_msg.header
    info_pub.publish(info_msg)
    except CvBridgeError as err:
    print err

    rate.sleep()

    return

    if __name__ == '__main__':
    try:
    main()
    except rospy.ROSInterruptException:
    pass