Skip to content

Commit 20d0709

Browse files
committed
[camera_calibration] Enable to select range policy for 16 bit images
1 parent 9488475 commit 20d0709

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

camera_calibration/nodes/cameracalibrator.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ def main():
132132
group.add_option("--max-chessboard-speed", type="float", default=-1.0,
133133
help="Do not use samples where the calibration pattern is moving faster \
134134
than this speed in px/frame. Set to eg. 0.5 for rolling shutter cameras.")
135+
parser.add_option("-r", "--range-policy",
136+
type="string", default="upper",
137+
help="For 16 bit images, the policy to use for determining the range of pixel values to use for thresholding. Choose from 'upper', 'dynamic', or 'legacy'.")
138+
135139

136140
parser.add_option_group(group)
137141

@@ -219,10 +223,13 @@ def main():
219223
else:
220224
checkerboard_flags = cv2.CALIB_CB_FAST_CHECK
221225

226+
range_policy = options.range_policy
227+
assert range_policy in ['upper', 'dynamic', 'legacy'], "Invalid range policy: %s" % range_policy
228+
222229
rospy.init_node('cameracalibrator')
223230
node = OpenCVCalibrationNode(boards, options.service_check, sync, calib_flags, fisheye_calib_flags, pattern, options.camera_name,
224231
checkerboard_flags=checkerboard_flags, max_chessboard_speed=options.max_chessboard_speed,
225-
queue_size=options.queue_size)
232+
queue_size=options.queue_size, range_policy=range_policy)
226233
rospy.spin()
227234

228235
if __name__ == "__main__":

camera_calibration/src/camera_calibration/calibrator.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class Calibrator():
318318
Base class for calibration system
319319
"""
320320
def __init__(self, boards, flags=0, fisheye_flags = 0, pattern=Patterns.Chessboard, name='',
321-
checkerboard_flags=cv2.CALIB_CB_FAST_CHECK, max_chessboard_speed = -1.0):
321+
checkerboard_flags=cv2.CALIB_CB_FAST_CHECK, max_chessboard_speed = -1.0,
322+
range_policy="upper"):
322323
# Ordering the dimensions for the different detectors is actually a minefield...
323324
if pattern == Patterns.Chessboard:
324325
# Make sure n_cols > n_rows to agree with OpenCV CB detector output
@@ -353,6 +354,7 @@ def __init__(self, boards, flags=0, fisheye_flags = 0, pattern=Patterns.Chessboa
353354
self.last_frame_corners = None
354355
self.last_frame_ids = None
355356
self.max_chessboard_speed = max_chessboard_speed
357+
self.range_policy = range_policy
356358

357359
def mkgray(self, msg):
358360
"""
@@ -362,7 +364,27 @@ def mkgray(self, msg):
362364
# TODO: get a Python API in cv_bridge to check for the image depth.
363365
if self.br.encoding_to_dtype_with_channels(msg.encoding)[0] in ['uint16', 'int16']:
364366
mono16 = self.br.imgmsg_to_cv2(msg, '16UC1')
365-
mono8 = numpy.array(mono16 / 256, dtype=numpy.uint8)
367+
if self.range_policy == "upper":
368+
# this policy works when the image is too bright
369+
mono16 = self.br.imgmsg_to_cv2(msg, '16UC1')
370+
mono8 = numpy.array(mono16 / 256, dtype=numpy.uint8)
371+
elif self.range_policy == "dynamic":
372+
min_val, max_val, _, _ = cv2.minMaxLoc(mono16)
373+
value_range = max_val - min_val
374+
if value_range > 0:
375+
mono8_float = (mono16 - min_val) * (255.0 / value_range)
376+
else:
377+
mono8_float = mono16
378+
mono8 = mono8_float.astype(numpy.uint8)
379+
elif self.range_policy == "legacy":
380+
# revival of old behavior removed in
381+
# https://github.com/ros-perception/image_pipeline/pull/334
382+
# this policy works when the image is too dark which might be the case
383+
# with old IR cameras
384+
mono8 = numpy.array(numpy.clip(mono16, 0, 255), dtype=numpy.uint8)
385+
else:
386+
assert False, "Unknown range policy '%s'" % self.range_policy
387+
366388
return mono8
367389
elif 'FC1' in msg.encoding:
368390
# floating point image handling

camera_calibration/src/camera_calibration/camera_calibrator.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ def run(self):
109109

110110
class CalibrationNode:
111111
def __init__(self, boards, service_check = True, synchronizer = message_filters.TimeSynchronizer, flags = 0,
112-
fisheye_flags = 0, pattern=Patterns.Chessboard, camera_name='', checkerboard_flags = 0,
113-
max_chessboard_speed = -1, queue_size = 1):
112+
fisheye_flags = 0, pattern=Patterns.Chessboard, camera_name = '', checkerboard_flags = 0,
113+
max_chessboard_speed = -1, queue_size = 1, range_policy = "upper"):
114114
if service_check:
115115
# assume any non-default service names have been set. Wait for the service to become ready
116116
for svcname in ["camera", "left_camera", "right_camera"]:
@@ -132,6 +132,8 @@ def __init__(self, boards, service_check = True, synchronizer = message_filters.
132132
self._pattern = pattern
133133
self._camera_name = camera_name
134134
self._max_chessboard_speed = max_chessboard_speed
135+
self._range_policy = range_policy
136+
135137
lsub = message_filters.Subscriber('left', sensor_msgs.msg.Image)
136138
rsub = message_filters.Subscriber('right', sensor_msgs.msg.Image)
137139
ts = synchronizer([lsub, rsub], 4)
@@ -178,11 +180,11 @@ def handle_monocular(self, msg):
178180
if self._camera_name:
179181
self.c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
180182
checkerboard_flags=self._checkerboard_flags,
181-
max_chessboard_speed = self._max_chessboard_speed)
183+
max_chessboard_speed=self._max_chessboard_speed, range_policy=self._range_policy)
182184
else:
183185
self.c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
184186
checkerboard_flags=self.checkerboard_flags,
185-
max_chessboard_speed = self._max_chessboard_speed)
187+
max_chessboard_speed=self._max_chessboard_speed, range_policy=self._range_policy)
186188

187189
# This should just call the MonoCalibrator
188190
drawable = self.c.handle_msg(msg)
@@ -194,11 +196,11 @@ def handle_stereo(self, msg):
194196
if self._camera_name:
195197
self.c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
196198
checkerboard_flags=self._checkerboard_flags,
197-
max_chessboard_speed = self._max_chessboard_speed)
199+
max_chessboard_speed=self._max_chessboard_speeds, range_policy=self._range_policy)
198200
else:
199201
self.c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
200202
checkerboard_flags=self._checkerboard_flags,
201-
max_chessboard_speed = self._max_chessboard_speed)
203+
max_chessboard_speed=self._max_chessboard_speed, range_policy=self._range_policy)
202204

203205
drawable = self.c.handle_msg(msg)
204206
self.displaywidth = drawable.lscrib.shape[1] + drawable.rscrib.shape[1]

0 commit comments

Comments
 (0)