save_image_utility.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # @file saved_image_utility.cc
4 #
5 # Copyright 2013-2025
6 # Carnegie Robotics, LLC
7 # 4501 Hatfield Street, Pittsburgh, PA 15201
8 # http://www.carnegierobotics.com
9 #
10 # All rights reserved.
11 #
12 # Redistribution and use in source and binary forms, with or without
13 # modification, are permitted provided that the following conditions are met:
14 # * Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # * Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 # * Neither the name of the Carnegie Robotics, LLC nor the
20 # names of its contributors may be used to endorse or promote products
21 # derived from this software without specific prior written permission.
22 #
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 # DISCLAIMED. IN NO EVENT SHALL CARNEGIE ROBOTICS, LLC BE LIABLE FOR ANY
27 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #
34 # Significant history (date, user, job code, action):
35 # 2025-02-07, malvarado@carnegierobotics.com, IRAD, Created file.
36 #
37 
38 import argparse
39 import time
40 import cv2
41 
42 import libmultisense as lms
43 
44 def get_status_string(status):
45  output = f"Camera Time(ns): {status.time.camera_time}, "\
46  f"System Ok: {status.system_ok}, "
47 
48  temp = ""
49  if status.temperature:
50  temp = f"FPGA Temp (C): {status.temperature.fpga_temperature}, "\
51  f"Left Imager Temp (C): {status.temperature.left_imager_temperature}, "\
52  f"Right Imager Temp (C): {status.temperature.right_imager_temperature}, "
53 
54  power = ""
55  if status.power:
56  power = f"Input Voltage (V): {status.power.input_voltage}, "\
57  f"Input Current (A): {status.power.input_current}, "\
58  f"FPGA Power (W): {status.power.fpga_power}, "\
59 
60  stats = f"Received Messages {status.client_network.received_messages}, "\
61  f"Dropped Messages {status.client_network.dropped_messages}"
62 
63  return output + temp + power + stats
64 
65 def save_image(frame, source):
66  base_path = str(frame.frame_id) + "_" + str(source);
67 
68  if source == lms.DataSource.LEFT_DISPARITY_RAW:
69  depth_image = lms.create_depth_image(frame, lms.PixelFormat.MONO16, lms.DataSource.LEFT_DISPARITY_RAW, 65535)
70  if depth_image:
71  lms.write_image(depth_image, base_path + ".pgm")
72  elif source == lms.DataSource.LEFT_RECTIFIED_RAW:
73  lms.write_image(frame.get_image(source), base_path + ".pgm")
74  elif source == lms.DataSource.AUX_RAW:
75  bgr = lms.create_bgr_image(frame, lms.DataSource.AUX_RAW)
76  if bgr:
77  lms.write_image(bgr, base_path + ".ppm")
78 
79 def main(args):
80  channel_config = lms.ChannelConfig()
81  channel_config.ip_address = args.ip_address
82  channel_config.mtu = args.mtu
83 
84  with lms.Channel.create(channel_config) as channel:
85  if not channel:
86  print("Invalid channel")
87  return
88 
89  info = channel.get_info()
90 
91  print("Firmware build date : ", info.version.firmware_build_date)
92  print("Firmware version : ", info.version.firmware_version.to_string())
93  print("Hardware version : ", hex(info.version.hardware_version))
94 
95  config = channel.get_config()
96  config.frames_per_second = 9.0
97  status = channel.set_config(config)
98  if status != lms.Status.OK:
99  print("Cannot set configuration", lms.to_string(status))
100  exit(1)
101 
102  streams = []
103  if args.save_depth:
104  streams.append(lms.DataSource.LEFT_DISPARITY_RAW)
105  if args.save_left_rect:
106  streams.append(lms.DataSource.LEFT_RECTIFIED_RAW)
107  if args.save_color:
108  streams.append(lms.DataSource.AUX_RAW)
109 
110  if channel.start_streams(streams) != lms.Status.OK:
111  print("Unable to start streams")
112  exit(1)
113 
114  saved_images = 0
115 
116  while True:
117  if saved_images < args.number_of_images:
118  frame = channel.get_next_image_frame()
119  if frame:
120  for stream in streams:
121  save_image(frame, stream)
122 
123  saved_images += 1
124 
125  status = channel.get_system_status()
126  if status:
127  print(get_status_string(status))
128 
129  time.sleep(1)
130 
131 if __name__ == '__main__':
132  parser = argparse.ArgumentParser("LibMultiSense save image utility")
133  parser.add_argument("-a", "--ip_address", default="10.66.171.21", help="The IPv4 address of the MultiSense.")
134  parser.add_argument("-m", "--mtu", type=int, default=1500, help="The MTU to use to communicate with the camera.")
135  parser.add_argument("-n", "--number-of-images", type=int, default=1, help="The number of images to save.")
136  parser.add_argument("-d", "--save-depth", action='store_true', help="Save a 16 bit depth image.")
137  parser.add_argument("-l", "--save-left-rect", action='store_true', help="Save a left rectified image.")
138  parser.add_argument("-c", "--save-color", action='store_true', help="Save a color image.")
139  main(parser.parse_args())
multisense::create_bgr_image
std::optional< Image > create_bgr_image(const ImageFrame &frame, const DataSource &output_source)
Convert a YCbCr420 luma + chroma image into a BGR color image.
Definition: utilities.cc:340
save_image_utility.main
def main(args)
Definition: save_image_utility.py:79
save_image_utility.get_status_string
def get_status_string(status)
Definition: save_image_utility.py:44
multisense::create_depth_image
std::optional< Image > create_depth_image(const ImageFrame &frame, const Image::PixelFormat &depth_format, const DataSource &disparity_source, float invalid_value)
Create a depth image from a image frame.
Definition: utilities.cc:191
save_image_utility.save_image
def save_image(frame, source)
Definition: save_image_utility.py:65
multisense::write_image
bool write_image(const Image &image, const std::filesystem::path &path)
Write a image to a specific path on disk. The type of serialization is determined by the input path.
Definition: utilities.cc:176
multisense::to_string
std::string to_string(const Status &status)
Convert a status object to a user readable string.
Definition: utilities.cc:137


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09