def test_full_correction(self): """Round trip distortion/correction.""" # This is all based on values from liboptv/tests/check_imgcoord.c cal = Calibration() cal.set_pos(np.r_[0., 0., 40.]) cal.set_angles(np.r_[0., 0., 0.]) cal.set_primary_point(np.r_[0., 0., 10.]) cal.set_glass_vec(np.r_[0., 0., 20.]) cal.set_radial_distortion(np.zeros(3)) cal.set_decentering(np.zeros(2)) cal.set_affine_trans(np.r_[1, 0]) # reference metric positions: # Note the last value is different than in test_brown_affine() because # the iteration does not converge for a point too far out. ref_pos = np.array([ [0.1, 0.1], [1., -1.], [-5., 5.] ]) cal.set_radial_distortion(np.r_[0.001, 0., 0.]) distorted = distort_arr_brown_affine(ref_pos, cal) corrected = distorted_to_flat(distorted, cal) # default tight tolerance np.testing.assert_array_almost_equal(ref_pos, corrected, decimal=6)
def test_brown_affine(self): """Distortion and correction of pixel coordinates.""" # This is all based on values from liboptv/tests/check_imgcoord.c cal = Calibration() cal.set_pos(np.r_[0., 0., 40.]) cal.set_angles(np.r_[0., 0., 0.]) cal.set_primary_point(np.r_[0., 0., 10.]) cal.set_glass_vec(np.r_[0., 0., 20.]) cal.set_radial_distortion(np.zeros(3)) cal.set_decentering(np.zeros(2)) cal.set_affine_trans(np.r_[1, 0]) # reference metric positions: ref_pos = np.array([ [0.1, 0.1], [1., -1.], [-10., 10.] ]) # Perfect camera: distortion = identity. distorted = distort_arr_brown_affine(ref_pos, cal) np.testing.assert_array_almost_equal(distorted, ref_pos) # Some small radial distortion: cal.set_radial_distortion(np.r_[0.001, 0., 0.]) distorted = distort_arr_brown_affine(ref_pos, cal) self.failUnless(np.all(abs(distorted) > abs(ref_pos)))
class Test_image_coordinates(unittest.TestCase): def setUp(self): self.control = ControlParams(4) self.calibration = Calibration() def test_img_coord_typecheck(self): with self.assertRaises(TypeError): list = [[0 for x in range(3)] for x in range(10)] # initialize a 10x3 list (but not numpy matrix) flat_image_coordinates(list, self.control, out=None) with self.assertRaises(TypeError): flat_image_coordinates(np.empty((10, 2)), self.calibration, self.control.get_multimedia_params(), output=None) with self.assertRaises(TypeError): image_coordinates(np.empty((10, 3)), self.calibration, self.control.get_multimedia_params(), output=np.zeros((10, 3))) with self.assertRaises(TypeError): image_coordinates(np.zeros((10, 2)), self.calibration, self.control.get_multimedia_params(), output=np.zeros((10, 2))) def test_image_coord_regress(self): self.calibration.set_pos(np.array([0, 0, 40])) self.calibration.set_angles(np.array([0, 0, 0])) self.calibration.set_primary_point(np.array([0, 0, 10])) self.calibration.set_glass_vec(np.array([0, 0, 20])) self.calibration.set_radial_distortion(np.array([0, 0, 0])) self.calibration.set_decentering(np.array([0, 0])) self.calibration.set_affine_trans(np.array([1, 0])) self.mult = MultimediaParams(n1=1, n2=np.array([1]), n3=1, d=np.array([1])) input = np.array([[10., 5., -20.], [10., 5., -20.]]) # vec3d output = np.zeros((2, 2)) x = 10. / 6. y = x / 2. correct_output = np.array([[x, y], [x, y]]) flat_image_coordinates(input=input, cal=self.calibration, mult_params=self.mult, output=output) np.testing.assert_array_equal(output, correct_output) output=np.full((2,2), 999.) image_coordinates(input=input, cal=self.calibration, mult_params=self.mult, output=output) np.testing.assert_array_equal(output, correct_output)
def test_two_cameras(self): ori_tmpl = "testing_fodder/calibration/sym_cam{cam_num}.tif.ori" add_file = "testing_fodder/calibration/cam1.tif.addpar" orig_cal = Calibration() orig_cal.from_file( ori_tmpl.format(cam_num=1).encode(), add_file.encode()) proj_cal = Calibration() proj_cal.from_file( ori_tmpl.format(cam_num=3).encode(), add_file.encode()) # reorient cams: orig_cal.set_angles(np.r_[0., -np.pi / 4., 0.]) proj_cal.set_angles(np.r_[0., 3 * np.pi / 4., 0.]) cpar = ControlParams(4) cpar.read_control_par(b"testing_fodder/corresp/control.par") sens_size = cpar.get_image_size() vpar = VolumeParams() vpar.read_volume_par(b"testing_fodder/corresp/criteria.par") vpar.set_Zmin_lay([-10, -10]) vpar.set_Zmax_lay([10, 10]) mult_params = cpar.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # Central point translates to central point because cameras point # directly at each other. mid = np.r_[sens_size] / 2. line = epipolar_curve(mid, orig_cal, proj_cal, 5, cpar, vpar) self.failUnless(np.all(abs(line - mid) < 1e-6)) # An equatorial point draws a latitude. line = epipolar_curve(mid - np.r_[100., 0.], orig_cal, proj_cal, 5, cpar, vpar) np.testing.assert_array_equal(np.argsort(line[:, 0]), np.arange(5)[::-1]) self.failUnless(np.all(abs(line[:, 1] - mid[1]) < 1e-6))
def test_two_cameras(self): ori_tmpl = "testing_fodder/calibration/sym_cam{cam_num}.tif.ori" add_file = "testing_fodder/calibration/cam1.tif.addpar" orig_cal = Calibration() orig_cal.from_file(ori_tmpl.format(cam_num=1).encode(), add_file.encode()) proj_cal = Calibration() proj_cal.from_file(ori_tmpl.format(cam_num=3).encode(), add_file.encode()) # reorient cams: orig_cal.set_angles(np.r_[0., -np.pi/4., 0.]) proj_cal.set_angles(np.r_[0., 3*np.pi/4., 0.]) cpar = ControlParams(4) cpar.read_control_par(b"testing_fodder/corresp/control.par") sens_size = cpar.get_image_size() vpar = VolumeParams() vpar.read_volume_par(b"testing_fodder/corresp/criteria.par") vpar.set_Zmin_lay([-10, -10]) vpar.set_Zmax_lay([10, 10]) mult_params = cpar.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # Central point translates to central point because cameras point # directly at each other. mid = np.r_[sens_size]/2. line = epipolar_curve(mid, orig_cal, proj_cal, 5, cpar, vpar) self.failUnless(np.all(abs(line - mid) < 1e-6)) # An equatorial point draws a latitude. line = epipolar_curve( mid - np.r_[100., 0.], orig_cal, proj_cal, 5, cpar, vpar) np.testing.assert_array_equal(np.argsort(line[:,0]), np.arange(5)[::-1]) self.failUnless(np.all(abs(line[:,1] - mid[1]) < 1e-6))
class TestGradientDescent(unittest.TestCase): # Based on the C tests in liboptv/tests/check_orientation.c def setUp(self): control_file_name = r'testing_fodder/corresp/control.par' self.control = ControlParams(4) self.control.read_control_par(control_file_name) self.cal = Calibration() self.cal.from_file("testing_fodder/calibration/cam1.tif.ori", "testing_fodder/calibration/cam1.tif.addpar") self.orig_cal = Calibration() self.orig_cal.from_file("testing_fodder/calibration/cam1.tif.ori", "testing_fodder/calibration/cam1.tif.addpar") def test_external_calibration(self): """External calibration using clicked points.""" ref_pts = np.array([[-40., -25., 8.], [40., -15., 0.], [40., 15., 0.], [40., 0., 8.]]) # Fake the image points by back-projection targets = convert_arr_metric_to_pixel( image_coordinates(ref_pts, self.cal, self.control.get_multimedia_params()), self.control) # Jigg the fake detections to give raw_orient some challenge. targets[:, 1] -= 0.1 self.assertTrue( external_calibration(self.cal, ref_pts, targets, self.control)) np.testing.assert_array_almost_equal(self.cal.get_angles(), self.orig_cal.get_angles(), decimal=4) np.testing.assert_array_almost_equal(self.cal.get_pos(), self.orig_cal.get_pos(), decimal=3) def test_full_calibration(self): ref_pts = np.array([ a.flatten() for a in np.meshgrid(np.r_[-60:-30:4j], np.r_[0:15:4j], np.r_[0:15:4j]) ]).T # Fake the image points by back-projection targets = convert_arr_metric_to_pixel( image_coordinates(ref_pts, self.cal, self.control.get_multimedia_params()), self.control) # Full calibration works with TargetArray objects, not NumPy. target_array = TargetArray(len(targets)) for i in xrange(len(targets)): target_array[i].set_pnr(i) target_array[i].set_pos(targets[i]) # Perturb the calibration object, then compore result to original. self.cal.set_pos(self.cal.get_pos() + np.r_[15., -15., 15.]) self.cal.set_angles(self.cal.get_angles() + np.r_[-.5, .5, -.5]) ret, used, err_est = full_calibration(self.cal, ref_pts, target_array, self.control) np.testing.assert_array_almost_equal(self.cal.get_angles(), self.orig_cal.get_angles(), decimal=4) np.testing.assert_array_almost_equal(self.cal.get_pos(), self.orig_cal.get_pos(), decimal=3)
class Test_Calibration(unittest.TestCase): def setUp(self): self.input_ori_file_name = b"testing_fodder/calibration/cam1.tif.ori" self.input_add_file_name = b"testing_fodder/calibration/cam2.tif.addpar" self.output_directory = b"testing_fodder/calibration/testing_output/" # create a temporary output directory (will be deleted by the end of test) if not os.path.exists(self.output_directory): os.makedirs(self.output_directory) # create an instance of Calibration wrapper class self.cal = Calibration() def test_full_instantiate(self): pos = numpy.r_[1., 3., 5.] angs = numpy.r_[2., 4., 6.] prim_point = pos * 3 rad_dist = pos * 4 decent = pos[:2] * 5 affine = decent * 1.5 glass = pos * 7 cal = Calibration(pos, angs, prim_point, rad_dist, decent, affine, glass) numpy.testing.assert_array_equal(pos, cal.get_pos()) numpy.testing.assert_array_equal(angs, cal.get_angles()) numpy.testing.assert_array_equal(prim_point, cal.get_primary_point()) numpy.testing.assert_array_equal(rad_dist, cal.get_radial_distortion()) numpy.testing.assert_array_equal(decent, cal.get_decentering()) numpy.testing.assert_array_equal(affine, cal.get_affine()) numpy.testing.assert_array_equal(glass, cal.get_glass_vec()) def test_Calibration_instantiation(self): """Filling a calibration object by reading ori files""" self.output_ori_file_name = self.output_directory + b"output_ori" self.output_add_file_name = self.output_directory + b"output_add" # Using a round-trip test. self.cal.from_file(self.input_ori_file_name, self.input_add_file_name) self.cal.write(self.output_ori_file_name, self.output_add_file_name) self.assertTrue(filecmp.cmp(self.input_ori_file_name, self.output_ori_file_name, 0)) self.assertTrue(filecmp.cmp(self.input_add_file_name, self.output_add_file_name, 0)) def test_set_pos(self): """Set exterior position, only for admissible values""" # test set_pos() by passing a numpy array of 3 elements new_np = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_pos(new_np) # test getting position and assert that position is equal to set position numpy.testing.assert_array_equal(new_np, self.cal.get_pos()) # assert set_pos() raises ValueError exception when given more or less than 3 elements self.assertRaises(ValueError, self.cal.set_pos, numpy.array([1, 2, 3, 4])) self.assertRaises(ValueError, self.cal.set_pos, numpy.array([1, 2])) def test_set_angles(self): """set angles correctly""" dmatrix_before = self.cal.get_rotation_matrix() # dmatrix before setting angles angles_np = numpy.array([0.1111, 0.2222, 0.3333]) self.cal.set_angles(angles_np) dmatrix_after = self.cal.get_rotation_matrix() # dmatrix after setting angles numpy.testing.assert_array_equal(self.cal.get_angles(), angles_np) # assert dmatrix was recalculated (before vs after) self.assertFalse(numpy.array_equal(dmatrix_before, dmatrix_after)) self.assertRaises(ValueError, self.cal.set_angles, numpy.array([1, 2, 3, 4])) self.assertRaises(ValueError, self.cal.set_angles, numpy.array([1, 2])) def tearDown(self): # remove the testing output directory and its files shutil.rmtree(self.output_directory) def test_set_primary(self): """Set primary point (interior) position, only for admissible values""" new_pp = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_primary_point(new_pp) numpy.testing.assert_array_equal(new_pp, self.cal.get_primary_point()) self.assertRaises(ValueError, self.cal.set_primary_point, numpy.ones(4)) self.assertRaises(ValueError, self.cal.set_primary_point, numpy.ones(2)) def test_set_radial(self): """Set radial distortion, only for admissible values""" new_rd = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_radial_distortion(new_rd) numpy.testing.assert_array_equal(new_rd, self.cal.get_radial_distortion()) self.assertRaises(ValueError, self.cal.set_radial_distortion, numpy.ones(4)) self.assertRaises(ValueError, self.cal.set_radial_distortion, numpy.ones(2)) def test_set_decentering(self): """Set radial distortion, only for admissible values""" new_de = numpy.array([111.1111, 222.2222]) self.cal.set_decentering(new_de) numpy.testing.assert_array_equal(new_de, self.cal.get_decentering()) self.assertRaises(ValueError, self.cal.set_decentering, numpy.ones(3)) self.assertRaises(ValueError, self.cal.set_decentering, numpy.ones(1)) def test_set_glass(self): """Set glass vector, only for admissible values""" new_gv = numpy.array([1., 2., 3.]) self.cal.set_glass_vec(new_gv) numpy.testing.assert_array_equal(new_gv, self.cal.get_glass_vec()) self.assertRaises(ValueError, self.cal.set_glass_vec, numpy.ones(2)) self.assertRaises(ValueError, self.cal.set_glass_vec, numpy.ones(1))
class TestGradientDescent(unittest.TestCase): # Based on the C tests in liboptv/tests/check_orientation.c def setUp(self): control_file_name = r'testing_fodder/corresp/control.par' self.control = ControlParams(4) self.control.read_control_par(control_file_name) self.cal = Calibration() self.cal.from_file( "testing_fodder/calibration/cam1.tif.ori", "testing_fodder/calibration/cam1.tif.addpar") self.orig_cal = Calibration() self.orig_cal.from_file( "testing_fodder/calibration/cam1.tif.ori", "testing_fodder/calibration/cam1.tif.addpar") def test_external_calibration(self): """External calibration using clicked points.""" ref_pts = np.array([ [-40., -25., 8.], [ 40., -15., 0.], [ 40., 15., 0.], [ 40., 0., 8.]]) # Fake the image points by back-projection targets = convert_arr_metric_to_pixel(image_coordinates( ref_pts, self.cal, self.control.get_multimedia_params()), self.control) # Jigg the fake detections to give raw_orient some challenge. targets[:,1] -= 0.1 self.assertTrue(external_calibration( self.cal, ref_pts, targets, self.control)) np.testing.assert_array_almost_equal( self.cal.get_angles(), self.orig_cal.get_angles(), decimal=4) np.testing.assert_array_almost_equal( self.cal.get_pos(), self.orig_cal.get_pos(), decimal=3) def test_full_calibration(self): ref_pts = np.array([a.flatten() for a in np.meshgrid( np.r_[-60:-30:4j], np.r_[0:15:4j], np.r_[0:15:4j])]).T # Fake the image points by back-projection targets = convert_arr_metric_to_pixel(image_coordinates( ref_pts, self.cal, self.control.get_multimedia_params()), self.control) # Full calibration works with TargetArray objects, not NumPy. target_array = TargetArray(len(targets)) for i in xrange(len(targets)): target_array[i].set_pnr(i) target_array[i].set_pos(targets[i]) # Perturb the calibration object, then compore result to original. self.cal.set_pos(self.cal.get_pos() + np.r_[15., -15., 15.]) self.cal.set_angles(self.cal.get_angles() + np.r_[-.5, .5, -.5]) ret, used, err_est = full_calibration( self.cal, ref_pts, target_array, self.control) np.testing.assert_array_almost_equal( self.cal.get_angles(), self.orig_cal.get_angles(), decimal=4) np.testing.assert_array_almost_equal( self.cal.get_pos(), self.orig_cal.get_pos(), decimal=3)
class Test_image_coordinates(unittest.TestCase): def setUp(self): self.control = ControlParams(4) self.calibration = Calibration() def test_img_coord_typecheck(self): with self.assertRaises(TypeError): list = [[0 for x in range(3)] for x in range(10) ] # initialize a 10x3 list (but not numpy matrix) flat_image_coordinates(list, self.control, out=None) with self.assertRaises(TypeError): flat_image_coordinates(np.empty((10, 2)), self.calibration, self.control.get_multimedia_params(), output=None) with self.assertRaises(TypeError): image_coordinates(np.empty((10, 3)), self.calibration, self.control.get_multimedia_params(), output=np.zeros((10, 3))) with self.assertRaises(TypeError): image_coordinates(np.zeros((10, 2)), self.calibration, self.control.get_multimedia_params(), output=np.zeros((10, 2))) def test_image_coord_regress(self): self.calibration.set_pos(np.array([0, 0, 40])) self.calibration.set_angles(np.array([0, 0, 0])) self.calibration.set_primary_point(np.array([0, 0, 10])) self.calibration.set_glass_vec(np.array([0, 0, 20])) self.calibration.set_radial_distortion(np.array([0, 0, 0])) self.calibration.set_decentering(np.array([0, 0])) self.calibration.set_affine_trans(np.array([1, 0])) self.mult = MultimediaParams(n1=1, n2=np.array([1]), n3=1, d=np.array([1])) input = np.array([[10., 5., -20.], [10., 5., -20.]]) # vec3d output = np.zeros((2, 2)) x = 10. / 6. y = x / 2. correct_output = np.array([[x, y], [x, y]]) flat_image_coordinates(input=input, cal=self.calibration, mult_params=self.mult, output=output) np.testing.assert_array_equal(output, correct_output) output = np.full((2, 2), 999.) image_coordinates(input=input, cal=self.calibration, mult_params=self.mult, output=output) np.testing.assert_array_equal(output, correct_output)
class Test_Calibration(unittest.TestCase): def setUp(self): self.input_ori_file_name = "testing_fodder/calibration/cam1.tif.ori" self.input_add_file_name = "testing_fodder/calibration/cam2.tif.addpar" self.output_directory = "testing_fodder/calibration/testing_output/" # create a temporary output directory (will be deleted by the end of test) if not os.path.exists(self.output_directory): os.makedirs(self.output_directory) # create an instance of Calibration wrapper class self.cal = Calibration() def test_Calibration_instantiation(self): """Filling a calibration object by reading ori files""" self.output_ori_file_name = self.output_directory + "output_ori" self.output_add_file_name = self.output_directory + "output_add" # Using a round-trip test. self.cal.from_file(self.input_ori_file_name, self.input_add_file_name) self.cal.write(self.output_ori_file_name, self.output_add_file_name) self.assertTrue(filecmp.cmp(self.input_ori_file_name, self.output_ori_file_name, 0)) self.assertTrue(filecmp.cmp(self.input_add_file_name, self.output_add_file_name, 0)) def test_set_pos(self): """Set exterior position, only for admissible values""" # test set_pos() by passing a numpy array of 3 elements new_np = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_pos(new_np) # test getting position and assert that position is equal to set position numpy.testing.assert_array_equal(new_np, self.cal.get_pos()) # assert set_pos() raises ValueError exception when given more or less than 3 elements self.assertRaises(ValueError, self.cal.set_pos, numpy.array([1, 2, 3, 4])) self.assertRaises(ValueError, self.cal.set_pos, numpy.array([1, 2])) def test_set_angles(self): """set angles correctly""" dmatrix_before = self.cal.get_rotation_matrix() # dmatrix before setting angles angles_np = numpy.array([0.1111, 0.2222, 0.3333]) self.cal.set_angles(angles_np) dmatrix_after = self.cal.get_rotation_matrix() # dmatrix after setting angles numpy.testing.assert_array_equal(self.cal.get_angles(), angles_np) # assert dmatrix was recalculated (before vs after) self.assertFalse(numpy.array_equal(dmatrix_before, dmatrix_after)) self.assertRaises(ValueError, self.cal.set_angles, numpy.array([1, 2, 3, 4])) self.assertRaises(ValueError, self.cal.set_angles, numpy.array([1, 2])) def tearDown(self): # remove the testing output directory and its files shutil.rmtree(self.output_directory) def test_set_primary(self): """Set primary point (interior) position, only for admissible values""" new_pp = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_primary_point(new_pp) numpy.testing.assert_array_equal(new_pp, self.cal.get_primary_point()) self.assertRaises(ValueError, self.cal.set_primary_point, numpy.ones(4)) self.assertRaises(ValueError, self.cal.set_primary_point, numpy.ones(2)) def test_set_radial(self): """Set radial distortion, only for admissible values""" new_rd = numpy.array([111.1111, 222.2222, 333.3333]) self.cal.set_radial_distortion(new_rd) numpy.testing.assert_array_equal(new_rd, self.cal.get_radial_distortion()) self.assertRaises(ValueError, self.cal.set_radial_distortion, numpy.ones(4)) self.assertRaises(ValueError, self.cal.set_radial_distortion, numpy.ones(2)) def test_set_decentering(self): """Set radial distortion, only for admissible values""" new_de = numpy.array([111.1111, 222.2222]) self.cal.set_decentering(new_de) numpy.testing.assert_array_equal(new_de, self.cal.get_decentering()) self.assertRaises(ValueError, self.cal.set_decentering, numpy.ones(3)) self.assertRaises(ValueError, self.cal.set_decentering, numpy.ones(1)) def test_set_glass(self): """Set glass vector, only for admissible values""" new_gv = numpy.array([1., 2., 3.]) self.cal.set_glass_vec(new_gv) numpy.testing.assert_array_equal(new_gv, self.cal.get_glass_vec()) self.assertRaises(ValueError, self.cal.set_glass_vec, numpy.ones(2)) self.assertRaises(ValueError, self.cal.set_glass_vec, numpy.ones(1))