Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 from io import BytesIO
00019 import os
00020 from PIL import Image
00021 import rosbag
00022 from sensor_msgs.msg import CompressedImage
00023 from sensor_msgs.msg import Image as smImage
00024 from std_msgs.msg import String
00025
00026
00027 def compress_image(msg):
00028 """
00029 Take a sensor_msgs/Image
00030 return a sensor_msgs/CompressedImage
00031 """
00032
00033
00034
00035
00036
00037 img = Image.fromstring("L", (msg.width, msg.height), msg.data,
00038 'raw', "L", 0, 1)
00039
00040 output = BytesIO()
00041 img.save(output, format='png')
00042 output.flush()
00043
00044 output_msg = CompressedImage()
00045 output_msg.header = msg.header
00046 output_msg.format = 'png'
00047 output_msg.data = output.getvalue()
00048
00049 encoding_msg = String()
00050 encoding_msg.data = msg.encoding
00051 return output_msg, encoding_msg
00052
00053
00054 def uncompress_image(compressed_msg, encoding):
00055 """
00056 Take a sensor_msgs/CompressedImage and encoding
00057 This will assume the compression has ignored the encoding and
00058 will apply the encoding
00059 return a sensor_msgs/Image
00060 """
00061 fh = BytesIO(compressed_msg.data)
00062 img = Image.open(fh)
00063
00064 output_msg = smImage()
00065 output_msg.header = compressed_msg.header
00066 output_msg.width, output_msg.height = img.size
00067 output_msg.encoding = encoding
00068 output_msg.is_bigendian = False
00069 output_msg.step = output_msg.width
00070 output_msg.data = img.tostring()
00071 return output_msg
00072
00073
00074 def image_topic_basename(topic):
00075 """ A convenience method for stripping the endings off an image topic"""
00076 endings = ['compressed', 'encoding', 'image_raw']
00077 for e in endings:
00078 if topic.endswith(e):
00079 return topic[:-1 * len(e)]
00080 raise Exception("invalid topic for truncation %s looking for endings %s" %
00081 (topic, endings))
00082
00083
00084 class EncodingCache:
00085
00086 """ A class for caching the encoding type for each topic. This will only
00087 work if the encoding does not change. """
00088
00089 def __init__(self):
00090 self.encoding_map = {}
00091
00092 def lookup_encoding(self, topic):
00093 if topic in self.encoding_map:
00094 return self.encoding_map[topic]
00095 else:
00096 raise Exception("failed to find encoding for topic %s in %s" %
00097 (topic, self.encoding_map))
00098
00099 def insert_encoding(self, topic, encoding):
00100 self.encoding_map[topic] = encoding
00101
00102
00103 def compress(bagfile_in, bagfile_out):
00104 """ Iterate over bagfile_in and compress images into bagfile_out """
00105 with rosbag.Bag(bagfile_in) as bag:
00106 with rosbag.Bag(bagfile_out, 'w') as outbag:
00107 process_log = {}
00108 print("Compressing %s into %s" % (bagfile_in, bagfile_out))
00109 for topic, msg, t in bag.read_messages():
00110 if topic.endswith('image_raw'):
00111
00112 bname = image_topic_basename(topic)
00113 try:
00114 msg, encoding_msg = compress_image(msg)
00115 encoding_topic = bname + "encoding"
00116 topic = bname + "compressed"
00117 outbag.write(encoding_topic, encoding_msg, t)
00118 if bname in process_log:
00119 process_log[bname] += 1
00120 else:
00121 process_log[bname] = 1
00122 except Exception as ex:
00123 print("Exception: %s when parsing msg. Not compressing" % ex)
00124
00125
00126 outbag.write(topic, msg, t)
00127 if not process_log:
00128 print("No images compressed")
00129 for t, c in process_log.items():
00130 print("Compressed %s message on topic %simage_raw" % (c, t))
00131
00132
00133 def uncompress(bagfile_in, bagfile_out):
00134 """ Iterate over bagfile_in and decompress images into bagfile_out """
00135 with rosbag.Bag(bagfile_in) as bag:
00136 with rosbag.Bag(bagfile_out, 'w') as outbag:
00137 process_log = {}
00138 print("Decompressing %s into %s" % (bagfile_in, bagfile_out))
00139 encoding_cache = EncodingCache()
00140 for topic, msg, t in bag.read_messages():
00141 bname = image_topic_basename(topic)
00142 if topic.endswith('encoding'):
00143 encoding_cache.insert_encoding(bname, msg.data)
00144 continue
00145 if topic.endswith('compressed'):
00146
00147 try:
00148 enc = encoding_cache.lookup_encoding(bname)
00149 msg = uncompress_image(msg, enc)
00150 topic = bname + 'image_raw'
00151 if bname in process_log:
00152 process_log[bname] += 1
00153 else:
00154 process_log[bname] = 1
00155 except Exception as ex:
00156 print("Exception: %s when parsing msg. Not decompressing" % ex)
00157
00158
00159 outbag.write(topic, msg, t)
00160 if not process_log:
00161 print("No images decompressed")
00162 for t, c in process_log.items():
00163 print("Decompressed %s message on topic %scompressed" % (c, t))