image_cal_utility.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # @file image_cal_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-03-25, malvarado@carnegierobotics.com, IRAD, Created file.
36 #
37 
38 import argparse
39 import cv2
40 import numpy as np
41 import os
42 
43 import libmultisense as lms
44 
45 def read_cal(intrinsics, extrinsics, index):
46  cal = lms.CameraCalibration()
47 
48  cal.K = intrinsics.getNode("M" + str(index)).mat()
49  cal.D = list(intrinsics.getNode("D" + str(index)).mat()[0])
50  cal.R = extrinsics.getNode("R" + str(index)).mat()
51  cal.P = extrinsics.getNode("P" + str(index)).mat()
52 
53  if len(cal.D) == 5:
54  cal.distortion_type = lms.DistortionType.PLUMBBOB
55  elif len(cal.D) == 8:
56  cal.distortion_type = lms.DistortionType.RATIONAL_POLYNOMIAL
57  else:
58  cal.distortion_type = lms.DistortionType.NONE
59 
60  return cal
61 
62 def write_cal(intrinsics, extrinsics, index, camera_cal):
63  intrinsics.write("M" + str(index), np.array(camera_cal.K))
64  intrinsics.write("D" + str(index), np.array([camera_cal.D]))
65  extrinsics.write("P" + str(index), np.array(camera_cal.P))
66  extrinsics.write("R" + str(index), np.array(camera_cal.R))
67 
68 def main(args):
69  channel_config = lms.ChannelConfig()
70  channel_config.ip_address = args.ip_address
71  channel_config.mtu = args.mtu
72 
73  with lms.Channel.create(channel_config) as channel:
74  if not channel:
75  print("Invalid channel")
76  exit(1)
77 
78  calibration = channel.get_calibration()
79 
80  if args.set_cal:
81  print("Attempting to set the MultiSense calibration")
82 
83  intrinsics = cv2.FileStorage(args.intrinsics, cv2.FILE_STORAGE_READ)
84  extrinsics = cv2.FileStorage(args.extrinsics, cv2.FILE_STORAGE_READ)
85 
86  calibration.left = read_cal(intrinsics, extrinsics, 1)
87  calibration.right = read_cal(intrinsics, extrinsics, 2)
88  if calibration.aux:
89  calibration.aux = read_cal(intrinsics, extrinsics, 3)
90 
91  if channel.set_calibration(calibration) != lms.Status.OK:
92  print("Unable to set the calibration")
93  exit(1)
94 
95  print("Image calibration successfully updated")
96  else:
97  if not args.disable_confirmation and (os.path.exists(args.intrinsics) or os.path.exists(args.extrinsics)):
98  print("One or both of the input file already exists\n")
99  res = input("Really overwrite these files? (y/n):")[0]
100  if res != 'Y' and res != 'y':
101  print("Aborting")
102  exit(1)
103 
104  intrinsics = cv2.FileStorage(args.intrinsics, cv2.FILE_STORAGE_WRITE)
105  extrinsics = cv2.FileStorage(args.extrinsics, cv2.FILE_STORAGE_WRITE)
106 
107  write_cal(intrinsics, extrinsics, 1, calibration.left)
108  write_cal(intrinsics, extrinsics, 2, calibration.right)
109  if calibration.aux:
110  write_cal(intrinsics, extrinsics, 3, calibration.aux)
111 
112 if __name__ == '__main__':
113  parser = argparse.ArgumentParser("LibMultiSense save image utility")
114  parser.add_argument("-a", "--ip_address", default="10.66.171.21", help="The IPv4 address of the MultiSense.")
115  parser.add_argument("-m", "--mtu", type=int, default=1500, help="The MTU to use to communicate with the camera.")
116  parser.add_argument("-i", "--intrinsics", required=True, help="The path to the intrinsics file to read from/write to.")
117  parser.add_argument("-e", "--extrinsics", required=True, help="The path to the extrinsics file to read from/write to.")
118  parser.add_argument("-s", "--set-cal", action='store_true', help="Write the calibration to the camera")
119  parser.add_argument("-y", "--disable-confirmation", action='store_true', help="Disable confirmation prompts")
120  main(parser.parse_args())
image_cal_utility.write_cal
def write_cal(intrinsics, extrinsics, index, camera_cal)
Definition: image_cal_utility.py:62
image_cal_utility.read_cal
def read_cal(intrinsics, extrinsics, index)
Definition: image_cal_utility.py:45
image_cal_utility.main
def main(args)
Definition: image_cal_utility.py:68
multisense::CameraCalibration
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:115


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