Skip to content

Commit fbf954d

Browse files
committed
adding --mono_before_stereo option to do combined monocular and stereo calibration for a camera pair
1 parent 00e7c02 commit fbf954d

File tree

3 files changed

+88
-30
lines changed

3 files changed

+88
-30
lines changed

camera_calibration/nodes/cameracalibrator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ def main():
108108
group.add_option("--max-chessboard-speed", type="float", default=-1.0,
109109
help="Do not use samples where the calibration pattern is moving faster \
110110
than this speed in px/frame. Set to eg. 0.5 for rolling shutter cameras.")
111-
111+
group.add_option("--mono-before-stereo", action='store_true', default=False,
112+
help="Independently perform monocular calibration before stereo calibration")
112113
parser.add_option_group(group)
113114

114115
options, args = parser.parse_args()
@@ -191,7 +192,7 @@ def main():
191192
rospy.init_node('cameracalibrator')
192193
node = OpenCVCalibrationNode(boards, options.service_check, sync, calib_flags, fisheye_calib_flags, pattern, options.camera_name,
193194
checkerboard_flags=checkerboard_flags, max_chessboard_speed=options.max_chessboard_speed,
194-
queue_size=options.queue_size)
195+
queue_size=options.queue_size, mono_before_stereo=options.mono_before_stereo)
195196
rospy.spin()
196197

197198
if __name__ == "__main__":

camera_calibration/src/camera_calibration/calibrator.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ class StereoCalibrator(Calibrator):
915915
def __init__(self, *args, **kwargs):
916916
if 'name' not in kwargs:
917917
kwargs['name'] = 'narrow_stereo'
918+
self.lcal = kwargs.pop('lcal', None)
919+
self.rcal = kwargs.pop('rcal', None)
918920
super(StereoCalibrator, self).__init__(*args, **kwargs)
919921
self.l = MonoCalibrator(*args, **kwargs)
920922
self.r = MonoCalibrator(*args, **kwargs)
@@ -955,10 +957,26 @@ def collect_corners(self, limages, rimages):
955957

956958
def cal_fromcorners(self, good):
957959
# Perform monocular calibrations
958-
lcorners = [(l, b) for (l, r, b) in good]
959-
rcorners = [(r, b) for (l, r, b) in good]
960-
self.l.cal_fromcorners(lcorners)
961-
self.r.cal_fromcorners(rcorners)
960+
if self.lcal and self.rcal:
961+
self.lcal.do_calibration()
962+
self.rcal.do_calibration()
963+
self.l.intrinsics = self.lcal.intrinsics
964+
self.l.distortion = self.lcal.distortion
965+
self.r.intrinsics = self.rcal.intrinsics
966+
self.r.distortion = self.rcal.distortion
967+
self.l.R = self.lcal.R
968+
self.r.R = self.rcal.R
969+
self.l.P = self.lcal.P
970+
self.r.P = self.rcal.P
971+
self.l.mapx = self.lcal.mapx
972+
self.l.mapy = self.lcal.mapy
973+
self.r.mapx = self.rcal.mapx
974+
self.r.mapy = self.rcal.mapy
975+
else:
976+
lcorners = [(l, b) for (l, r, b) in good]
977+
rcorners = [(r, b) for (l, r, b) in good]
978+
self.l.cal_fromcorners(lcorners)
979+
self.r.cal_fromcorners(rcorners)
962980

963981
lipts = [ l for (l, _, _) in good ]
964982
ripts = [ r for (_, r, _) in good ]

camera_calibration/src/camera_calibration/camera_calibrator.py

100755100644
Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def run(self):
111111
class CalibrationNode:
112112
def __init__(self, boards, service_check = True, synchronizer = message_filters.TimeSynchronizer, flags = 0,
113113
fisheye_flags = 0, pattern=Patterns.Chessboard, camera_name='', checkerboard_flags = 0,
114-
max_chessboard_speed = -1, queue_size = 1):
114+
max_chessboard_speed = -1, queue_size = 1, mono_before_stereo=False):
115115
if service_check:
116116
# assume any non-default service names have been set. Wait for the service to become ready
117117
for svcname in ["camera", "left_camera", "right_camera"]:
@@ -133,6 +133,7 @@ def __init__(self, boards, service_check = True, synchronizer = message_filters.
133133
self._pattern = pattern
134134
self._camera_name = camera_name
135135
self._max_chessboard_speed = max_chessboard_speed
136+
self._mono_before_stereo = mono_before_stereo
136137
lsub = message_filters.Subscriber('left', sensor_msgs.msg.Image)
137138
rsub = message_filters.Subscriber('right', sensor_msgs.msg.Image)
138139
ts = synchronizer([lsub, rsub], 4)
@@ -154,6 +155,9 @@ def __init__(self, boards, service_check = True, synchronizer = message_filters.
154155
self.c = None
155156

156157
self._last_display = None
158+
self.lcal = None
159+
self.rcal = None
160+
self.lock = threading.Lock()
157161

158162
mth = ConsumerThread(self.q_mono, self.handle_monocular)
159163
mth.setDaemon(True)
@@ -172,35 +176,51 @@ def queue_monocular(self, msg):
172176
self.q_mono.put(msg)
173177

174178
def queue_stereo(self, lmsg, rmsg):
175-
self.q_stereo.put((lmsg, rmsg))
179+
if self._mono_before_stereo:
180+
if self.lcal == None:
181+
self.q_mono.put(lmsg)
182+
elif self.rcal == None:
183+
self.q_mono.put(rmsg)
184+
else:
185+
self.q_stereo.put((lmsg, rmsg))
186+
else:
187+
self.q_stereo.put((lmsg, rmsg))
188+
189+
def init_monocular(self):
190+
if self._camera_name:
191+
c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
192+
checkerboard_flags=self._checkerboard_flags,
193+
max_chessboard_speed = self._max_chessboard_speed)
194+
else:
195+
c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
196+
checkerboard_flags=self.checkerboard_flags,
197+
max_chessboard_speed = self._max_chessboard_speed)
198+
return c
199+
200+
def init_stereo(self):
201+
if self._camera_name:
202+
c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
203+
checkerboard_flags=self._checkerboard_flags,
204+
max_chessboard_speed = self._max_chessboard_speed,
205+
lcal=self.lcal, rcal=self.rcal)
206+
else:
207+
c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
208+
checkerboard_flags=self._checkerboard_flags,
209+
max_chessboard_speed = self._max_chessboard_speed,
210+
lcal=self.lcal, rcal=self.rcal)
211+
return c
176212

177213
def handle_monocular(self, msg):
178214
if self.c == None:
179-
if self._camera_name:
180-
self.c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
181-
checkerboard_flags=self._checkerboard_flags,
182-
max_chessboard_speed = self._max_chessboard_speed)
183-
else:
184-
self.c = MonoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
185-
checkerboard_flags=self.checkerboard_flags,
186-
max_chessboard_speed = self._max_chessboard_speed)
187-
215+
self.c = self.init_monocular()
188216
# This should just call the MonoCalibrator
189217
drawable = self.c.handle_msg(msg)
190218
self.displaywidth = drawable.scrib.shape[1]
191219
self.redraw_monocular(drawable)
192220

193221
def handle_stereo(self, msg):
194222
if self.c == None:
195-
if self._camera_name:
196-
self.c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern, name=self._camera_name,
197-
checkerboard_flags=self._checkerboard_flags,
198-
max_chessboard_speed = self._max_chessboard_speed)
199-
else:
200-
self.c = StereoCalibrator(self._boards, self._calib_flags, self._fisheye_calib_flags, self._pattern,
201-
checkerboard_flags=self._checkerboard_flags,
202-
max_chessboard_speed = self._max_chessboard_speed)
203-
223+
self.c = self.init_stereo()
204224
drawable = self.c.handle_msg(msg)
205225
self.displaywidth = drawable.lscrib.shape[1] + drawable.rscrib.shape[1]
206226
self.redraw_stereo(drawable)
@@ -265,10 +285,29 @@ def on_mouse(self, event, x, y, flags, param):
265285
if event == cv2.EVENT_LBUTTONDOWN and self.displaywidth < x:
266286
if self.c.goodenough:
267287
if 180 <= y < 280:
268-
print("**** Calibrating ****")
269-
self.c.do_calibration()
270-
self.buttons(self._last_display)
271-
self.queue_display.put(self._last_display)
288+
if self._mono_before_stereo:
289+
if self.lcal == None:
290+
self.lcal = self.c
291+
self.q_mono.clear()
292+
self.q_stereo.clear()
293+
self.c = self.init_monocular()
294+
elif self.rcal == None:
295+
self.lock.acquire()
296+
self.rcal = self.c
297+
self.q_mono.clear()
298+
self.q_stereo.clear()
299+
self.c = self.init_stereo()
300+
self.lock.release()
301+
else:
302+
print("**** Calibrating ****")
303+
self.c.do_calibration()
304+
self.buttons(self._last_display)
305+
self.queue_display.put(self._last_display)
306+
else:
307+
print("**** Calibrating ****")
308+
self.c.do_calibration()
309+
self.buttons(self._last_display)
310+
self.queue_display.put(self._last_display)
272311
if self.c.calibrated:
273312
if 280 <= y < 380:
274313
self.c.do_save()

0 commit comments

Comments
 (0)