Skip to content

Commit 0057db6

Browse files
committed
adding --mono_before_stereo option to do combined monocular and stereo calibration for a camera pair
1 parent 49cb230 commit 0057db6

File tree

3 files changed

+88
-31
lines changed

3 files changed

+88
-31
lines changed

camera_calibration/nodes/cameracalibrator.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ def main():
9090
group.add_option("--max-chessboard-speed", type="float", default=-1.0,
9191
help="Do not use samples where the calibration pattern is moving faster \
9292
than this speed in px/frame. Set to eg. 0.5 for rolling shutter cameras.")
93+
group.add_option("--mono-before-stereo", action='store_true', default=False,
94+
help="Independently perform monocular calibration before stereo calibration")
9395
parser.add_option_group(group)
9496
options, args = parser.parse_args()
9597

@@ -150,7 +152,7 @@ def main():
150152
rospy.init_node('cameracalibrator')
151153
node = OpenCVCalibrationNode(boards, options.service_check, sync, calib_flags, pattern, options.camera_name,
152154
checkerboard_flags=checkerboard_flags, max_chessboard_speed=options.max_chessboard_speed,
153-
queue_size=options.queue_size)
155+
queue_size=options.queue_size, mono_before_stereo=options.mono_before_stereo)
154156
rospy.spin()
155157

156158
if __name__ == "__main__":

camera_calibration/src/camera_calibration/calibrator.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,8 @@ class StereoCalibrator(Calibrator):
881881
def __init__(self, *args, **kwargs):
882882
if 'name' not in kwargs:
883883
kwargs['name'] = 'narrow_stereo'
884+
self.lcal = kwargs.pop('lcal', None)
885+
self.rcal = kwargs.pop('rcal', None)
884886
super(StereoCalibrator, self).__init__(*args, **kwargs)
885887
self.l = MonoCalibrator(*args, **kwargs)
886888
self.r = MonoCalibrator(*args, **kwargs)
@@ -921,10 +923,26 @@ def collect_corners(self, limages, rimages):
921923

922924
def cal_fromcorners(self, good):
923925
# Perform monocular calibrations
924-
lcorners = [(l, b) for (l, r, b) in good]
925-
rcorners = [(r, b) for (l, r, b) in good]
926-
self.l.cal_fromcorners(lcorners)
927-
self.r.cal_fromcorners(rcorners)
926+
if self.lcal and self.rcal:
927+
self.lcal.do_calibration()
928+
self.rcal.do_calibration()
929+
self.l.intrinsics = self.lcal.intrinsics
930+
self.l.distortion = self.lcal.distortion
931+
self.r.intrinsics = self.rcal.intrinsics
932+
self.r.distortion = self.rcal.distortion
933+
self.l.R = self.lcal.R
934+
self.r.R = self.rcal.R
935+
self.l.P = self.lcal.P
936+
self.r.P = self.rcal.P
937+
self.l.mapx = self.lcal.mapx
938+
self.l.mapy = self.lcal.mapy
939+
self.r.mapx = self.rcal.mapx
940+
self.r.mapy = self.rcal.mapy
941+
else:
942+
lcorners = [(l, b) for (l, r, b) in good]
943+
rcorners = [(r, b) for (l, r, b) in good]
944+
self.l.cal_fromcorners(lcorners)
945+
self.r.cal_fromcorners(rcorners)
928946

929947
lipts = [ l for (l, _, _) in good ]
930948
ripts = [ r for (_, r, _) in good ]

camera_calibration/src/camera_calibration/camera_calibrator.py

100755100644
+63-26
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def run(self):
109109
class CalibrationNode:
110110
def __init__(self, boards, service_check = True, synchronizer = message_filters.TimeSynchronizer, flags = 0,
111111
pattern=Patterns.Chessboard, camera_name='', checkerboard_flags = 0, max_chessboard_speed = -1,
112-
queue_size = 1):
112+
queue_size = 1, mono_before_stereo=False):
113113
if service_check:
114114
# assume any non-default service names have been set. Wait for the service to become ready
115115
for svcname in ["camera", "left_camera", "right_camera"]:
@@ -130,6 +130,7 @@ def __init__(self, boards, service_check = True, synchronizer = message_filters.
130130
self._pattern = pattern
131131
self._camera_name = camera_name
132132
self._max_chessboard_speed = max_chessboard_speed
133+
self._mono_before_stereo = mono_before_stereo
133134
lsub = message_filters.Subscriber('left', sensor_msgs.msg.Image)
134135
rsub = message_filters.Subscriber('right', sensor_msgs.msg.Image)
135136
ts = synchronizer([lsub, rsub], 4)
@@ -149,8 +150,10 @@ def __init__(self, boards, service_check = True, synchronizer = message_filters.
149150
self.q_stereo = BufferQueue(queue_size)
150151

151152
self.c = None
152-
153153
self._last_display = None
154+
self.lcal = None
155+
self.rcal = None
156+
self.lock = threading.Lock()
154157

155158
mth = ConsumerThread(self.q_mono, self.handle_monocular)
156159
mth.setDaemon(True)
@@ -169,40 +172,55 @@ def queue_monocular(self, msg):
169172
self.q_mono.put(msg)
170173

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

174209
def handle_monocular(self, msg):
175210
if self.c == None:
176-
if self._camera_name:
177-
self.c = MonoCalibrator(self._boards, self._calib_flags, self._pattern, name=self._camera_name,
178-
checkerboard_flags=self._checkerboard_flags,
179-
max_chessboard_speed = self._max_chessboard_speed)
180-
else:
181-
self.c = MonoCalibrator(self._boards, self._calib_flags, self._pattern,
182-
checkerboard_flags=self.checkerboard_flags,
183-
max_chessboard_speed = self._max_chessboard_speed)
184-
211+
self.c = self.init_monocular()
185212
# This should just call the MonoCalibrator
186213
drawable = self.c.handle_msg(msg)
187214
self.displaywidth = drawable.scrib.shape[1]
188215
self.redraw_monocular(drawable)
189216

190217
def handle_stereo(self, msg):
191218
if self.c == None:
192-
if self._camera_name:
193-
self.c = StereoCalibrator(self._boards, self._calib_flags, self._pattern, name=self._camera_name,
194-
checkerboard_flags=self._checkerboard_flags,
195-
max_chessboard_speed = self._max_chessboard_speed)
196-
else:
197-
self.c = StereoCalibrator(self._boards, self._calib_flags, self._pattern,
198-
checkerboard_flags=self._checkerboard_flags,
199-
max_chessboard_speed = self._max_chessboard_speed)
200-
219+
self.c = self.init_stereo()
201220
drawable = self.c.handle_msg(msg)
202221
self.displaywidth = drawable.lscrib.shape[1] + drawable.rscrib.shape[1]
203222
self.redraw_stereo(drawable)
204223

205-
206224
def check_set_camera_info(self, response):
207225
if response.success:
208226
return True
@@ -262,10 +280,29 @@ def on_mouse(self, event, x, y, flags, param):
262280
if event == cv2.EVENT_LBUTTONDOWN and self.displaywidth < x:
263281
if self.c.goodenough:
264282
if 180 <= y < 280:
265-
print("**** Calibrating ****")
266-
self.c.do_calibration()
267-
self.buttons(self._last_display)
268-
self.queue_display.put(self._last_display)
283+
if self._mono_before_stereo:
284+
if self.lcal == None:
285+
self.lcal = self.c
286+
self.q_mono.clear()
287+
self.q_stereo.clear()
288+
self.c = self.init_monocular()
289+
elif self.rcal == None:
290+
self.lock.acquire()
291+
self.rcal = self.c
292+
self.q_mono.clear()
293+
self.q_stereo.clear()
294+
self.c = self.init_stereo()
295+
self.lock.release()
296+
else:
297+
print("**** Calibrating ****")
298+
self.c.do_calibration()
299+
self.buttons(self._last_display)
300+
self.queue_display.put(self._last_display)
301+
else:
302+
print("**** Calibrating ****")
303+
self.c.do_calibration()
304+
self.buttons(self._last_display)
305+
self.queue_display.put(self._last_display)
269306
if self.c.calibrated:
270307
if 280 <= y < 380:
271308
self.c.do_save()

0 commit comments

Comments
 (0)