diff --git a/sksurgerycalibration/video/video_calibration_driver_stereo.py b/sksurgerycalibration/video/video_calibration_driver_stereo.py index b64a790..50518b0 100644 --- a/sksurgerycalibration/video/video_calibration_driver_stereo.py +++ b/sksurgerycalibration/video/video_calibration_driver_stereo.py @@ -53,27 +53,32 @@ def grab_data(self, but will return empty arrays if no points were detected. So, no points is not an error. Its an expected condition. - :param left_image: RGB image. - :param right_image: RGB image. + :param left_image: BGR image. + :param right_image: BGR image. :param device_tracking: transformation for the tracked device :param calibration_object_tracking: transformation of tracked calibration object :return: The number of points grabbed. """ - number_of_points = 0 + number_left = 0 + number_right = 0 # This can return None's if none are found. left_ids, left_object_points, left_image_points = \ self.point_detector.get_points(left_image) - if left_ids is not None and \ - left_ids.shape[0] >= self.minimum_points_per_frame: + if left_ids is not None: + number_left = left_ids.shape[0] + + if number_left >= self.minimum_points_per_frame: right_ids, right_object_points, right_image_points = \ self.point_detector.get_points(right_image) - if right_ids is not None and \ - right_ids.shape[0] >= self.minimum_points_per_frame: + if right_ids is not None: + number_right = right_ids.shape[0] + + if number_right >= self.minimum_points_per_frame: left_ids, left_image_points, left_object_points = \ cu.convert_pd_to_opencv(left_ids, @@ -97,14 +102,14 @@ def grab_data(self, self.tracking_data.push(device_tracking, calibration_object_tracking) - number_of_points = \ - left_image_points.shape[0] + \ - right_image_points.shape[0] + number_of_points = number_left + number_right - LOGGER.info("Grabbed: Returning %s points.", + LOGGER.info("Grabbed: Returning (%s+%s)=%s points.", + str(number_left), + str(number_right), str(number_of_points)) - return number_of_points + return number_left, number_right def calibrate(self, flags=cv2.CALIB_USE_INTRINSIC_GUESS, diff --git a/tests/data/2020_01_20_storz/.DS_Store b/tests/data/2020_01_20_storz/.DS_Store deleted file mode 100644 index 5eeaf3c..0000000 Binary files a/tests/data/2020_01_20_storz/.DS_Store and /dev/null differ diff --git a/tests/video/test_charuco_plus_chessboard.py b/tests/video/test_charuco_plus_chessboard.py index ee71f7a..94bbcdf 100644 --- a/tests/video/test_charuco_plus_chessboard.py +++ b/tests/video/test_charuco_plus_chessboard.py @@ -18,7 +18,6 @@ def test_stereo_davinci(): files.sort() for file in files: image = cv2.imread(file) - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) print("Loaded:" + str(file)) left_images.append(image) assert(len(left_images) == 59) @@ -28,7 +27,6 @@ def test_stereo_davinci(): files.sort() for file in files: image = cv2.imread(file) - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) print("Loaded:" + str(file)) right_images.append(image) assert (len(right_images) == 59) @@ -38,9 +36,11 @@ def test_stereo_davinci(): calibrator = sc.StereoVideoCalibrationDriver(detector, minimum_number_of_points_per_image) for i, _ in enumerate(left_images): try: - number_of_points = calibrator.grab_data(left_images[i], right_images[i]) - if number_of_points < 2 * minimum_number_of_points_per_image: - print("Image pair:" + str(i) + ", SKIPPED, due to not enough points") + number_left, number_right = calibrator.grab_data(left_images[i], right_images[i]) + if number_left < minimum_number_of_points_per_image: + print("Image pair:" + str(i) + ", left image, SKIPPED, due to not enough points") + if number_right < minimum_number_of_points_per_image: + print("Image pair:" + str(i) + ", right image, SKIPPED, due to not enough points") except ValueError as ve: print("Image pair:" + str(i) + ", FAILED, due to:" + str(ve)) except TypeError as te: diff --git a/tests/video/test_chessboard_calibration.py b/tests/video/test_chessboard_calibration.py index d2a1a6b..e42cfc4 100644 --- a/tests/video/test_chessboard_calibration.py +++ b/tests/video/test_chessboard_calibration.py @@ -10,6 +10,7 @@ import sksurgerycalibration.video.video_calibration_driver_mono as mc import sksurgerycalibration.video.video_calibration_driver_stereo as sc import sksurgerycalibration.video.video_calibration_utils as vu +import tests.video.video_testing_utils as vtu def get_iterative_reference_data(): @@ -37,7 +38,6 @@ def test_chessboard_mono(): files = glob.glob('tests/data/laparoscope_calibration/left/*.png') for file in files: image = cv2.imread(file) - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) images.append(image) # This illustrates that the PointDetector sub-class holds the knowledge of the model. @@ -118,23 +118,8 @@ def test_chessboard_mono(): def test_chessboard_stereo(): - left_images = [] - files = glob.glob('tests/data/laparoscope_calibration/left/*.png') - files.sort() - for file in files: - image = cv2.imread(file) - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - left_images.append(image) - assert(len(left_images) == 9) - - right_images = [] - files = glob.glob('tests/data/laparoscope_calibration/right/*.png') - files.sort() - for file in files: - image = cv2.imread(file) - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - right_images.append(image) - assert (len(right_images) == 9) + left_images, right_images \ + = vtu.load_left_right_pngs('tests/data/laparoscope_calibration/', 9) chessboard_detector = \ pd.ChessboardPointDetector((14, 10), @@ -147,8 +132,9 @@ def test_chessboard_stereo(): # Repeatedly grab data, until you have enough. for i, _ in enumerate(left_images): - successful = calibrator.grab_data(left_images[i], right_images[i]) - assert successful > 0 + number_left, number_right = calibrator.grab_data(left_images[i], right_images[i]) + assert number_left > 0 + assert number_right > 0 assert not calibrator.is_device_tracked() assert not calibrator.is_calibration_target_tracked() @@ -157,7 +143,7 @@ def test_chessboard_stereo(): # Just for a regression test, checking reprojection error, and recon error. assert reproj_err < 0.7 - assert recon_err < 1.7 + assert recon_err < 1.8 print("Stereo, default=" + str(reproj_err) + ", " + str(recon_err)) # Now test rerunning where we optimize the extrinsics with other params fixed. @@ -172,7 +158,7 @@ def test_chessboard_stereo(): ) assert reproj_err < 0.7 - assert recon_err < 1.7 + assert recon_err < 1.8 print("Stereo, extrinsics=" + str(reproj_err) + ", " + str(recon_err)) # Test iterative calibration. @@ -183,5 +169,5 @@ def test_chessboard_stereo(): reference_points, reference_image_size) assert reproj_err < 0.7 - assert recon_err < 1.5 + assert recon_err < 1.6 print("Stereo, iterative=" + str(reproj_err) + ", " + str(recon_err)) diff --git a/tests/video/test_data_param_io.py b/tests/video/test_data_param_io.py index a9ed132..799aafd 100644 --- a/tests/video/test_data_param_io.py +++ b/tests/video/test_data_param_io.py @@ -9,6 +9,7 @@ import sksurgeryimage.calibration.chessboard_point_detector as pd import sksurgerycalibration.video.video_calibration_driver_mono as mc import sksurgerycalibration.video.video_calibration_driver_stereo as sc +import tests.video.video_testing_utils as vtu def test_chessboard_mono_io(): @@ -49,21 +50,8 @@ def test_chessboard_mono_io(): def test_chessboard_stereo_io(): - left_images = [] - files = glob.glob('tests/data/laparoscope_calibration/left/*.png') - files.sort() - for file in files: - image = cv2.imread(file) - left_images.append(image) - assert(len(left_images) == 9) - - right_images = [] - files = glob.glob('tests/data/laparoscope_calibration/right/*.png') - files.sort() - for file in files: - image = cv2.imread(file) - right_images.append(image) - assert (len(right_images) == 9) + left_images, right_images \ + = vtu.load_left_right_pngs('tests/data/laparoscope_calibration/', 9) chessboard_detector = \ pd.ChessboardPointDetector((14, 10), @@ -75,8 +63,9 @@ def test_chessboard_stereo_io(): sc.StereoVideoCalibrationDriver(chessboard_detector, 140) for i, _ in enumerate(left_images): - successful = calibrator.grab_data(left_images[i], right_images[i], np.eye(4), np.eye(3)) - assert successful > 0 + num_left, num_right = calibrator.grab_data(left_images[i], right_images[i], np.eye(4), np.eye(3)) + assert num_left > 0 + assert num_right > 0 # Then do calibration reproj_err_1, recon_err_1, params_1 = calibrator.calibrate() diff --git a/tests/video/test_hand_eye.py b/tests/video/test_hand_eye.py index 2d1c0b5..2f04c1b 100644 --- a/tests/video/test_hand_eye.py +++ b/tests/video/test_hand_eye.py @@ -40,6 +40,7 @@ def load_images_from_glob(glob_pattern): return images + def load_tracking_from_glob(glob_pattern): """ Load tracking data from files based on a glob pattern. """ tracking = [] @@ -53,7 +54,8 @@ def load_tracking_from_glob(glob_pattern): def test_handeye_calibration_mono(): - """ Load mono data (only using left channel) and tracking, do video and + """ + Load mono data (only using left channel) and tracking, do video and handeye calibration, compare results against expected values. """ images = load_images_from_glob( @@ -96,15 +98,16 @@ def test_handeye_calibration_mono(): # These values are taken from a previous successful run # Not objective measures of correctness - expected_reproj_error = 14.93867 - expected_recon_error = 5.530625 + expected_reproj_error = 14.97731 + expected_recon_error = 5.434362 assert proj_err == pytest.approx(expected_reproj_error, rel=1e-4) assert recon_err == pytest.approx(expected_recon_error, rel=1e-4) def test_handeye_calibration_stereo(): - """ Load Stereo data and tracking, do video and + """ + Load Stereo data and tracking, do video and handeye calibration, compare results against expected values. """ left_images = load_images_from_glob( @@ -126,7 +129,8 @@ def test_handeye_calibration_stereo(): min_number_of_points_per_image = 50 detector = \ - chpd.CharucoPlusChessboardPointDetector(error_if_no_chessboard=False) + chpd.CharucoPlusChessboardPointDetector(charuco_filtering=True, + error_if_no_chessboard=False) calibrator = \ vidcal.video_calibration_driver_stereo.StereoVideoCalibrationDriver( @@ -135,8 +139,12 @@ def test_handeye_calibration_stereo(): # Grab data from images/tracking arrays for left, right, device, calib_obj in \ zip(left_images, right_images, device_tracking, obj_tracking): - successful = calibrator.grab_data(left, right, device, calib_obj) - assert successful > 0 + num_left, num_right = calibrator.grab_data(left, + right, + device, + calib_obj) + assert num_left > 0 + assert num_right > 0 reproj_err_1, recon_err_1, _ = calibrator.calibrate() @@ -151,8 +159,8 @@ def test_handeye_calibration_stereo(): # These values are taken from a previous successful run # Not objective measures of correctness - expected_reproj_error = 13.452010 - expected_recon_error = 1.394778 + expected_reproj_error = 13.543016 + expected_recon_error = 1.383223 assert proj_err == pytest.approx(expected_reproj_error, rel=1e-4) assert recon_err == pytest.approx(expected_recon_error, rel=1e-4) @@ -175,4 +183,3 @@ def test_load_data_stereo_calib(): assert len(stereo_calib.tracking_data.calibration_tracking_array) == 10 assert len(stereo_calib.video_data.left_data.images_array) == 10 assert len(stereo_calib.video_data.right_data.images_array) == 10 - \ No newline at end of file diff --git a/tests/video/video_testing_utils.py b/tests/video/video_testing_utils.py new file mode 100644 index 0000000..12841fb --- /dev/null +++ b/tests/video/video_testing_utils.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +""" Various utilities to help testing. """ + +import os +import glob +import cv2 + + +def load_left_right_pngs(dir_name, expected_number): + """Given a dir_name, loads left/*.png and right/*.png""" + left_images = [] + files = glob.glob(os.path.join(dir_name, "left", "*.png")) + files.sort() + for file in files: + image = cv2.imread(file) + left_images.append(image) + assert len(left_images) == expected_number + + right_images = [] + files = glob.glob(os.path.join(dir_name, "right", "*.png")) + files.sort() + for file in files: + image = cv2.imread(file) + right_images.append(image) + assert len(right_images) == expected_number + + return left_images, right_images