def test_single_camera_point_positions(self): """Point positions for a single camera case""" num_cams = 1 # prepare MultimediaParams cpar_file = b'testing_fodder/single_cam/parameters/ptv.par' vpar_file = b'testing_fodder/single_cam/parameters/criteria.par' cpar = ControlParams(num_cams) cpar.read_control_par(cpar_file) mult_params = cpar.get_multimedia_params() vpar = VolumeParams() vpar.read_volume_par(vpar_file) ori_name = b'testing_fodder/single_cam/calibration/cam_1.tif.ori' add_name = b'testing_fodder/single_cam/calibration/cam_1.tif.addpar' calibs = [] # read calibration for each camera from files new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_name) calibs.append(new_cal) # 3d point points = np.array([[1, 1, 0], [-1, -1, 0]], dtype=float) targs_plain = [] targs_jigged = [] jigg_amp = 0.4 new_plain_targ = image_coordinates( points, calibs[0], mult_params) targs_plain.append(new_plain_targ) jigged_points = points - np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates( jigged_points, calibs[0], mult_params) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1,0,2) targs_jigged = np.array(targs_jigged).transpose(1,0,2) skew_dist_plain = point_positions(targs_plain, cpar, calibs, vpar) skew_dist_jigged = point_positions(targs_jigged, cpar, calibs, vpar) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any(np.linalg.norm(jigged_points - skew_dist_jigged[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position after jigging.')
def test_single_camera_point_positions(self): """Point positions for a single camera case""" num_cams = 1 # prepare MultimediaParams cpar_file = b'testing_fodder/single_cam/parameters/ptv.par' vpar_file = b'testing_fodder/single_cam/parameters/criteria.par' cpar = ControlParams(num_cams) cpar.read_control_par(cpar_file) mult_params = cpar.get_multimedia_params() vpar = VolumeParams() vpar.read_volume_par(vpar_file) ori_name = b'testing_fodder/single_cam/calibration/cam_1.tif.ori' add_name = b'testing_fodder/single_cam/calibration/cam_1.tif.addpar' calibs = [] # read calibration for each camera from files new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_name) calibs.append(new_cal) # 3d point points = np.array([[1, 1, 0], [-1, -1, 0]], dtype=float) targs_plain = [] targs_jigged = [] jigg_amp = 0.4 new_plain_targ = image_coordinates(points, calibs[0], mult_params) targs_plain.append(new_plain_targ) jigged_points = points - np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates(jigged_points, calibs[0], mult_params) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1, 0, 2) targs_jigged = np.array(targs_jigged).transpose(1, 0, 2) skew_dist_plain = point_positions(targs_plain, cpar, calibs, vpar) skew_dist_jigged = point_positions(targs_jigged, cpar, calibs, vpar) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any( np.linalg.norm(jigged_points - skew_dist_jigged[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position after jigging.')
def test_full_corresp(self): """Full scene correspondences""" print "about to dump core" cpar = ControlParams(4) cpar.read_control_par("testing_fodder/corresp/control.par") vpar = VolumeParams() vpar.read_volume_par("testing_fodder/corresp/criteria.par") # Cameras are at so high angles that opposing cameras don't see each # other in the normal air-glass-water setting. cpar.get_multimedia_params().set_layers([1.0001], [1.]) cpar.get_multimedia_params().set_n3(1.0001) cals = [] img_pts = [] corrected = [] for c in xrange(4): cal = Calibration() cal.from_file( "testing_fodder/calibration/sym_cam%d.tif.ori" % (c + 1), "testing_fodder/calibration/cam1.tif.addpar") cals.append(cal) # Generate test targets. targs = TargetArray(16) for row, col in np.ndindex(4, 4): targ_ix = row*4 + col # Avoid symmetric case: if (c % 2): targ_ix = 15 - targ_ix targ = targs[targ_ix] pos3d = 10*np.array([[col, row, 0]], dtype=np.float64) pos2d = image_coordinates( pos3d, cal, cpar.get_multimedia_params()) targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0]) targ.set_pnr(targ_ix) targ.set_pixel_counts(25, 5, 5) targ.set_sum_grey_value(10) img_pts.append(targs) mc = MatchedCoords(targs, cpar, cal) corrected.append(mc) sorted_pos, sorted_corresp, num_targs = correspondences( img_pts, corrected, cals, vpar, cpar) self.failUnlessEqual(num_targs, 16)
def test_full_corresp(self): """Full scene correspondences""" cpar = ControlParams(4) cpar.read_control_par(r"testing_fodder/corresp/control.par") vpar = VolumeParams() vpar.read_volume_par(r"testing_fodder/corresp/criteria.par") # Cameras are at so high angles that opposing cameras don't see each # other in the normal air-glass-water setting. cpar.get_multimedia_params().set_layers([1.0001], [1.]) cpar.get_multimedia_params().set_n3(1.0001) cals = [] img_pts = [] corrected = [] for c in xrange(4): cal = Calibration() cal.from_file( "testing_fodder/calibration/sym_cam%d.tif.ori" % (c + 1), "testing_fodder/calibration/cam1.tif.addpar") cals.append(cal) # Generate test targets. targs = TargetArray(16) for row, col in np.ndindex(4, 4): targ_ix = row * 4 + col # Avoid symmetric case: if (c % 2): targ_ix = 15 - targ_ix targ = targs[targ_ix] pos3d = 10 * np.array([[col, row, 0]], dtype=np.float64) pos2d = image_coordinates(pos3d, cal, cpar.get_multimedia_params()) targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0]) targ.set_pnr(targ_ix) targ.set_pixel_counts(25, 5, 5) targ.set_sum_grey_value(10) img_pts.append(targs) mc = MatchedCoords(targs, cpar, cal) corrected.append(mc) sorted_pos, sorted_corresp, num_targs = correspondences( img_pts, corrected, cals, vpar, cpar) self.failUnlessEqual(num_targs, 16)
def _button_init_guess_fired(self): if self.need_reset: self.reset_show_images() self.need_reset = 0 self.cal_points = self._read_cal_points() self.cals = [] for i_cam in range(self.n_cams): cal = Calibration() tmp = self.cpar.get_cal_img_base_name(i_cam) cal.from_file(tmp + '.ori', tmp + '.addpar') self.cals.append(cal) for i_cam in range(self.n_cams): self._project_cal_points(i_cam)
def test_dumbbell(self): # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17.5, 42, 0], [-17.5, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = 'testing_fodder/dumbbell/cam{cam_num}.tif.ori' add_file = 'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name.encode(), add_file=add_file.encode()) calibs.append(new_cal) for cam_cal in calibs: new_plain_targ = flat_image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) targs_plain = np.array(targs_plain).transpose(1, 0, 2) # The cameras are not actually fully calibrated, so the result is not # an exact 0. The test is that changing the expected distance changes # the measure. tf = dumbbell_target_func(targs_plain, self.control, calibs, 35., 0.) self.assertAlmostEqual(tf, 7.14860, 5) # just a regression test # As we check the db length, the measure increases... tf_len = dumbbell_target_func(targs_plain, self.control, calibs, 35., 1.) self.assertTrue(tf_len > tf) # ...but not as much as when giving the wrong length. tf_too_long = dumbbell_target_func(targs_plain, self.control, calibs, 25., 1.) self.assertTrue(tf_too_long > tf_len > tf)
def test_dumbbell(self): # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17.5, 42, 0], [-17.5, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/dumbbell/cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = flat_image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) targs_plain = np.array(targs_plain).transpose(1,0,2) # The cameras are not actually fully calibrated, so the result is not # an exact 0. The test is that changing the expected distance changes # the measure. tf = dumbbell_target_func(targs_plain, self.control, calibs, 35., 0.) self.assertAlmostEqual(tf, 7.14860, 5) # just a regression test # As we check the db length, the measure increases... tf_len = dumbbell_target_func( targs_plain, self.control, calibs, 35., 1.) self.assertTrue(tf_len > tf) # ...but not as much as when giving the wrong length. tf_too_long = dumbbell_target_func( targs_plain, self.control, calibs, 25., 1.) self.assertTrue(tf_too_long > tf_len > tf)
def test_single_cam_corresp(self): """Single camera correspondence""" cpar = ControlParams(1) cpar.read_control_par(b"testing_fodder/single_cam/parameters/ptv.par") vpar = VolumeParams() vpar.read_volume_par(b"testing_fodder/single_cam/parameters/criteria.par") # Cameras are at so high angles that opposing cameras don't see each # other in the normal air-glass-water setting. cpar.get_multimedia_params().set_layers([1.], [1.]) cpar.get_multimedia_params().set_n3(1.) cals = [] img_pts = [] corrected = [] cal = Calibration() cal.from_file( b"testing_fodder/single_cam/calibration/cam_1.tif.ori", b"testing_fodder/single_cam/calibration/cam_1.tif.addpar") cals.append(cal) # Generate test targets. targs = TargetArray(9) for row, col in np.ndindex(3, 3): targ_ix = row*3 + col targ = targs[targ_ix] pos3d = 10*np.array([[col, row, 0]], dtype=np.float64) pos2d = image_coordinates( pos3d, cal, cpar.get_multimedia_params()) targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0]) targ.set_pnr(targ_ix) targ.set_pixel_counts(25, 5, 5) targ.set_sum_grey_value(10) img_pts.append(targs) mc = MatchedCoords(targs, cpar, cal) corrected.append(mc) _, _, num_targs = correspondences( img_pts, corrected, cals, vpar, cpar) self.failUnlessEqual(num_targs, 9)
def test_single_cam_corresp(self): """Single camera correspondence""" cpar = ControlParams(1) cpar.read_control_par("testing_fodder/single_cam/parameters/ptv.par") vpar = VolumeParams() vpar.read_volume_par( "testing_fodder/single_cam/parameters/criteria.par") # Cameras are at so high angles that opposing cameras don't see each # other in the normal air-glass-water setting. cpar.get_multimedia_params().set_layers([1.], [1.]) cpar.get_multimedia_params().set_n3(1.) cals = [] img_pts = [] corrected = [] cal = Calibration() cal.from_file( "testing_fodder/single_cam/calibration/cam_1.tif.ori", "testing_fodder/single_cam/calibration/cam_1.tif.addpar") cals.append(cal) # Generate test targets. targs = TargetArray(9) for row, col in np.ndindex(3, 3): targ_ix = row * 3 + col targ = targs[targ_ix] pos3d = 10 * np.array([[col, row, 0]], dtype=np.float64) pos2d = image_coordinates(pos3d, cal, cpar.get_multimedia_params()) targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0]) targ.set_pnr(targ_ix) targ.set_pixel_counts(25, 5, 5) targ.set_sum_grey_value(10) img_pts.append(targs) mc = MatchedCoords(targs, cpar, cal) corrected.append(mc) sorted_pos, sorted_corresp, num_targs = correspondences( img_pts, corrected, cals, vpar, cpar) self.failUnlessEqual(num_targs, 9)
def test_instantiate(self): """Creating a MatchedCoords object""" cal = Calibration() cpar = ControlParams(4) cal.from_file("testing_fodder/calibration/cam1.tif.ori", "testing_fodder/calibration/cam2.tif.addpar") cpar.read_control_par("testing_fodder/corresp/control.par") targs = read_targets("testing_fodder/frame/cam1.", 333) mc = MatchedCoords(targs, cpar, cal) pos, pnr = mc.as_arrays() # x sorted? self.failUnless(np.all(pos[1:, 0] > pos[:-1, 0])) # Manually verified order for the loaded data: np.testing.assert_array_equal( pnr, np.r_[6, 11, 10, 8, 1, 4, 7, 0, 2, 9, 5, 3, 12])
def py_determination_proc_c(n_cams, sorted_pos, sorted_corresp, corrected): """ Returns 3d positions """ # Control parameters cpar = ControlParams(n_cams) cpar.read_control_par(b'parameters/ptv.par') # Volume parameters vpar = VolumeParams() vpar.read_volume_par(b'parameters/criteria.par') cals =[] for i_cam in range(n_cams): cal = Calibration() tmp = cpar.get_cal_img_base_name(i_cam) cal.from_file(tmp + b'.ori', tmp + b'.addpar') cals.append(cal) # Distinction between quad/trip irrelevant here. sorted_pos = np.concatenate(sorted_pos, axis=1) sorted_corresp = np.concatenate(sorted_corresp, axis=1) flat = np.array([corrected[i].get_by_pnrs(sorted_corresp[i]) \ for i in range(len(cals))]) pos, rcm = point_positions( flat.transpose(1,0,2), cpar, cals, vpar) if len(cals) < 4: print_corresp = -1*np.ones((4,sorted_corresp.shape[1])) print_corresp[:len(cals),:] = sorted_corresp else: print_corresp = sorted_corresp # Save rt_is in a temporary file fname = b"".join([default_naming['corres'],b'.123456789']) # hard-coded frame number with open(fname, 'w') as rt_is: rt_is.write(str(pos.shape[0]) + '\n') for pix, pt in enumerate(pos): pt_args = (pix + 1,) + tuple(pt) + tuple(print_corresp[:,pix]) rt_is.write("%4d %9.3f %9.3f %9.3f %4d %4d %4d %4d\n" % pt_args)
def test_instantiate(self): """Creating a MatchedCoords object""" cal = Calibration() cpar = ControlParams(4) cal.from_file( b"testing_fodder/calibration/cam1.tif.ori", b"testing_fodder/calibration/cam2.tif.addpar") cpar.read_control_par(b"testing_fodder/corresp/control.par") targs = read_targets("testing_fodder/frame/cam1.", 333) mc = MatchedCoords(targs, cpar, cal) pos, pnr = mc.as_arrays() # x sorted? self.failUnless(np.all(pos[1:,0] > pos[:-1,0])) # Manually verified order for the loaded data: np.testing.assert_array_equal( pnr, np.r_[6, 11, 10, 8, 1, 4, 7, 0, 2, 9, 5, 3, 12])
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 setUp(self): with open("testing_fodder/track/conf.yaml") as f: yaml_conf = yaml.load(f) seq_cfg = yaml_conf['sequence'] cals = [] img_base = [] for cix, cam_spec in enumerate(yaml_conf['cameras']): cam_spec.setdefault('addpar_file', None) cal = Calibration() cal.from_file(cam_spec['ori_file'], cam_spec['addpar_file']) cals.append(cal) img_base.append(seq_cfg['targets_template'].format(cam=cix + 1)) cpar = ControlParams(len(yaml_conf['cameras']), **yaml_conf['scene']) vpar = VolumeParams(**yaml_conf['correspondences']) tpar = TrackingParams(**yaml_conf['tracking']) spar = SequenceParams(image_base=img_base, frame_range=(seq_cfg['first'], seq_cfg['last'])) self.tracker = Tracker(cpar, vpar, tpar, spar, cals, framebuf_naming)
def setUp(self): with open("testing_fodder/track/conf.yaml") as f: yaml_conf = yaml.load(f) seq_cfg = yaml_conf['sequence'] cals = [] img_base = [] for cix, cam_spec in enumerate(yaml_conf['cameras']): cam_spec.setdefault('addpar_file', None) cal = Calibration() cal.from_file(cam_spec['ori_file'], cam_spec['addpar_file']) cals.append(cal) img_base.append(seq_cfg['targets_template'].format(cam=cix + 1)) cpar = ControlParams(len(yaml_conf['cameras']), **yaml_conf['scene']) vpar = VolumeParams(**yaml_conf['correspondences']) tpar = TrackingParams(**yaml_conf['tracking']) spar = SequenceParams( image_base=img_base, frame_range=(seq_cfg['first'], seq_cfg['last'])) self.tracker = Tracker(cpar, vpar, tpar, spar, cals, framebuf_naming)
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 py_determination_proc_c(n_cams, sorted_pos, sorted_corresp, corrected): """ Returns 3d positions """ # Control parameters cpar = ControlParams(n_cams) cpar.read_control_par('parameters/ptv.par') # Volume parameters vpar = VolumeParams() vpar.read_volume_par('parameters/criteria.par') cals = [] for i_cam in xrange(n_cams): cal = Calibration() tmp = cpar.get_cal_img_base_name(i_cam) cal.from_file(tmp + '.ori', tmp + '.addpar') cals.append(cal) # Distinction between quad/trip irrelevant here. sorted_pos = np.concatenate(sorted_pos, axis=1) sorted_corresp = np.concatenate(sorted_corresp, axis=1) flat = np.array([corrected[i].get_by_pnrs(sorted_corresp[i]) \ for i in xrange(len(cals))]) pos, rcm = point_positions(flat.transpose(1, 0, 2), cpar, cals, vpar) if len(cals) == 1: # single camera case sorted_corresp = np.tile(sorted_corresp, (4, 1)) sorted_corresp[1:, :] = -1 # Save rt_is in a temporary file frame = 123456789 # just a temporary workaround. todo: think how to write with open(default_naming['corres'] + '.' + str(frame), 'w') as rt_is: rt_is.write(str(pos.shape[0]) + '\n') for pix, pt in enumerate(pos): pt_args = (pix + 1, ) + tuple(pt) + tuple(sorted_corresp[:, pix]) rt_is.write("%4d %9.3f %9.3f %9.3f %4d %4d %4d %4d\n" % pt_args)
def py_start_proc_c(n_cams): """ Read parameters """ # Control parameters cpar = ControlParams(n_cams) cpar.read_control_par(b'parameters/ptv.par') # Sequence parameters spar = SequenceParams(num_cams=n_cams) spar.read_sequence_par(b'parameters/sequence.par', n_cams) # Volume parameters vpar = VolumeParams() vpar.read_volume_par(b'parameters/criteria.par') # Tracking parameters track_par = TrackingParams() track_par.read_track_par(b'parameters/track.par') # Target parameters tpar = TargetParams(n_cams) tpar.read(b'parameters/targ_rec.par') # Examine parameters, multiplane (single plane vs combined calibration) epar = par.ExamineParams() epar.read() # Calibration parameters cals = [] for i_cam in range(n_cams): cal = Calibration() tmp = cpar.get_cal_img_base_name(i_cam) cal.from_file(tmp + b'.ori', tmp + b'.addpar') cals.append(cal) return cpar, spar, vpar, track_par, tpar, cals, epar
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))
class Test_Orientation(unittest.TestCase): def setUp(self): self.input_ori_file_name = r'testing_fodder/calibration/cam1.tif.ori' self.input_add_file_name = r'testing_fodder/calibration/cam2.tif.addpar' self.control_file_name = r'testing_fodder/control_parameters/control.par' self.calibration = Calibration() self.calibration.from_file( self.input_ori_file_name, self.input_add_file_name) self.control = ControlParams(4) self.control.read_control_par(self.control_file_name) def test_match_detection_to_ref(self): """Match detection to reference (sortgrid)""" xyz_input = np.array([(10, 10, 10), (200, 200, 200), (600, 800, 100), (20, 10, 2000), (30, 30, 30)], dtype=float) coords_count = len(xyz_input) xy_img_pts_metric = image_coordinates( xyz_input, self.calibration, self.control.get_multimedia_params()) xy_img_pts_pixel = convert_arr_metric_to_pixel( xy_img_pts_metric, control=self.control) # convert to TargetArray object target_array = TargetArray(coords_count) for i in range(coords_count): target_array[i].set_pnr(i) target_array[i].set_pos( (xy_img_pts_pixel[i][0], xy_img_pts_pixel[i][1])) # create randomized target array indices = range(coords_count) shuffled_indices = range(coords_count) while indices == shuffled_indices: random.shuffle(shuffled_indices) rand_targ_array = TargetArray(coords_count) for i in range(coords_count): rand_targ_array[shuffled_indices[i]].set_pos(target_array[i].pos()) rand_targ_array[shuffled_indices[i]].set_pnr(target_array[i].pnr()) # match detection to reference matched_target_array = match_detection_to_ref(cal=self.calibration, ref_pts=xyz_input, img_pts=rand_targ_array, cparam=self.control) # assert target array is as before for i in range(coords_count): if matched_target_array[i].pos() != target_array[i].pos() \ or matched_target_array[i].pnr() != target_array[i].pnr(): self.fail() # pass ref_pts and img_pts with non-equal lengths with self.assertRaises(ValueError): match_detection_to_ref(cal=self.calibration, ref_pts=xyz_input, img_pts=TargetArray(coords_count - 1), cparam=self.control) def test_point_positions(self): """Point positions""" # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17, 42, 0], [17, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/calibration/sym_cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] targs_jigged = [] jigg_amp = 0.5 # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) if (cam_num % 2) == 0: jigged_points = points - np.r_[0, jigg_amp, 0] else: jigged_points = points + np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates( jigged_points, cam_cal, self.control.get_multimedia_params()) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1,0,2) targs_jigged = np.array(targs_jigged).transpose(1,0,2) skew_dist_plain = point_positions(targs_plain, self.control, calibs) skew_dist_jigged = point_positions(targs_jigged, self.control, calibs) if np.any(skew_dist_plain[1] > 1e-10): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_plain[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any(skew_dist_jigged[1] > 0.7): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_jigged[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_jigged[0], axis=1) > 0.1): self.fail('Rays converge on wrong position after jigging.') def test_dumbbell(self): # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17.5, 42, 0], [-17.5, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/dumbbell/cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = flat_image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) targs_plain = np.array(targs_plain).transpose(1,0,2) # The cameras are not actually fully calibrated, so the result is not # an exact 0. The test is that changing the expected distance changes # the measure. tf = dumbbell_target_func(targs_plain, self.control, calibs, 35., 0.) self.assertAlmostEqual(tf, 7.14860, 5) # just a regression test # As we check the db length, the measure increases... tf_len = dumbbell_target_func( targs_plain, self.control, calibs, 35., 1.) self.assertTrue(tf_len > tf) # ...but not as much as when giving the wrong length. tf_too_long = dumbbell_target_func( targs_plain, self.control, calibs, 25., 1.) self.assertTrue(tf_too_long > tf_len > tf)
def test_point_positions(self): """Point positions""" # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17, 42, 0], [17, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/calibration/sym_cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] targs_jigged = [] jigg_amp = 0.5 # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) if (cam_num % 2) == 0: jigged_points = points - np.r_[0, jigg_amp, 0] else: jigged_points = points + np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates( jigged_points, cam_cal, self.control.get_multimedia_params()) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1, 0, 2) targs_jigged = np.array(targs_jigged).transpose(1, 0, 2) skew_dist_plain = point_positions(targs_plain, self.control, calibs) skew_dist_jigged = point_positions(targs_jigged, self.control, calibs) if np.any(skew_dist_plain[1] > 1e-10): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_plain[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any(skew_dist_jigged[1] > 0.7): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_jigged[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_jigged[0], axis=1) > 0.1): self.fail('Rays converge on wrong position after jigging.')
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_Orientation(unittest.TestCase): def setUp(self): self.input_ori_file_name = r'testing_fodder/calibration/cam1.tif.ori' self.input_add_file_name = r'testing_fodder/calibration/cam2.tif.addpar' self.control_file_name = r'testing_fodder/control_parameters/control.par' self.calibration = Calibration() self.calibration.from_file(self.input_ori_file_name, self.input_add_file_name) self.control = ControlParams(4) self.control.read_control_par(self.control_file_name) def test_match_detection_to_ref(self): """Match detection to reference (sortgrid)""" xyz_input = np.array([(10, 10, 10), (200, 200, 200), (600, 800, 100), (20, 10, 2000), (30, 30, 30)], dtype=float) coords_count = len(xyz_input) xy_img_pts_metric = image_coordinates( xyz_input, self.calibration, self.control.get_multimedia_params()) xy_img_pts_pixel = convert_arr_metric_to_pixel(xy_img_pts_metric, control=self.control) # convert to TargetArray object target_array = TargetArray(coords_count) for i in range(coords_count): target_array[i].set_pnr(i) target_array[i].set_pos( (xy_img_pts_pixel[i][0], xy_img_pts_pixel[i][1])) # create randomized target array indices = range(coords_count) shuffled_indices = range(coords_count) while indices == shuffled_indices: random.shuffle(shuffled_indices) rand_targ_array = TargetArray(coords_count) for i in range(coords_count): rand_targ_array[shuffled_indices[i]].set_pos(target_array[i].pos()) rand_targ_array[shuffled_indices[i]].set_pnr(target_array[i].pnr()) # match detection to reference matched_target_array = match_detection_to_ref(cal=self.calibration, ref_pts=xyz_input, img_pts=rand_targ_array, cparam=self.control) # assert target array is as before for i in range(coords_count): if matched_target_array[i].pos() != target_array[i].pos() \ or matched_target_array[i].pnr() != target_array[i].pnr(): self.fail() # pass ref_pts and img_pts with non-equal lengths with self.assertRaises(ValueError): match_detection_to_ref(cal=self.calibration, ref_pts=xyz_input, img_pts=TargetArray(coords_count - 1), cparam=self.control) def test_point_positions(self): """Point positions""" # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17, 42, 0], [17, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/calibration/sym_cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] targs_jigged = [] jigg_amp = 0.5 # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) if (cam_num % 2) == 0: jigged_points = points - np.r_[0, jigg_amp, 0] else: jigged_points = points + np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates( jigged_points, cam_cal, self.control.get_multimedia_params()) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1, 0, 2) targs_jigged = np.array(targs_jigged).transpose(1, 0, 2) skew_dist_plain = point_positions(targs_plain, self.control, calibs) skew_dist_jigged = point_positions(targs_jigged, self.control, calibs) if np.any(skew_dist_plain[1] > 1e-10): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_plain[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any(skew_dist_jigged[1] > 0.7): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_jigged[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_jigged[0], axis=1) > 0.1): self.fail('Rays converge on wrong position after jigging.') def test_dumbbell(self): # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17.5, 42, 0], [-17.5, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/dumbbell/cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = flat_image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) targs_plain = np.array(targs_plain).transpose(1, 0, 2) # The cameras are not actually fully calibrated, so the result is not # an exact 0. The test is that changing the expected distance changes # the measure. tf = dumbbell_target_func(targs_plain, self.control, calibs, 35., 0.) self.assertAlmostEqual(tf, 7.14860, 5) # just a regression test # As we check the db length, the measure increases... tf_len = dumbbell_target_func(targs_plain, self.control, calibs, 35., 1.) self.assertTrue(tf_len > tf) # ...but not as much as when giving the wrong length. tf_too_long = dumbbell_target_func(targs_plain, self.control, calibs, 25., 1.) self.assertTrue(tf_too_long > tf_len > tf)
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 Test_transforms(unittest.TestCase): def setUp(self): self.input_control_par_file_name = "testing_fodder/control_parameters/control.par" self.control = ControlParams(4) self.control.read_control_par(self.input_control_par_file_name) self.input_ori_file_name = "testing_fodder/calibration/cam1.tif.ori" self.input_add_file_name = "testing_fodder/calibration/cam2.tif.addpar" self.calibration = Calibration() self.calibration.from_file(self.input_ori_file_name, self.input_add_file_name) def test_transforms_typecheck(self): """Transform bindings check types""" # Assert TypeError is raised when passing a non (n,2) shaped numpy ndarray with self.assertRaises(TypeError): list = [[0 for x in range(2)] for x in range(10) ] # initialize a 10x2 list (but not numpy matrix) convert_arr_pixel_to_metric(list, self.control, out=None) with self.assertRaises(TypeError): convert_arr_pixel_to_metric(np.empty((10, 3)), self.control, out=None) with self.assertRaises(TypeError): convert_arr_metric_to_pixel(np.empty((2, 1)), self.control, out=None) with self.assertRaises(TypeError): convert_arr_metric_to_pixel(np.zeros((11, 2)), self.control, out=np.zeros((12, 2))) def test_transforms_regress(self): """Transformed values are as before.""" input = np.full((3, 2), 100.) output = np.zeros((3, 2)) correct_output_pixel_to_metric = [[-8181., 6657.92], [-8181., 6657.92], [-8181., 6657.92]] correct_output_metric_to_pixel = [[646.60066007, 505.81188119], [646.60066007, 505.81188119], [646.60066007, 505.81188119]] # Test when passing an array for output convert_arr_pixel_to_metric(input, self.control, out=output) np.testing.assert_array_almost_equal(output, correct_output_pixel_to_metric, decimal=7) output = np.zeros((3, 2)) convert_arr_metric_to_pixel(input, self.control, out=output) np.testing.assert_array_almost_equal(output, correct_output_metric_to_pixel, decimal=7) # Test when NOT passing an array for output output = convert_arr_pixel_to_metric(input, self.control, out=None) np.testing.assert_array_almost_equal(output, correct_output_pixel_to_metric, decimal=7) output = np.zeros((3, 2)) output = convert_arr_metric_to_pixel(input, self.control, out=None) np.testing.assert_array_almost_equal(output, correct_output_metric_to_pixel, decimal=7) def test_transforms(self): """Transform in well-known setup gives precalculates results.""" cpar = ControlParams(1) cpar.set_image_size((1280, 1000)) cpar.set_pixel_size((0.1, 0.1)) metric_pos = np.array([[1., 1.], [-10., 15.], [20., -30.]]) pixel_pos = np.array([[650., 490.], [540., 350.], [840., 800.]]) np.testing.assert_array_almost_equal( pixel_pos, convert_arr_metric_to_pixel(metric_pos, cpar)) np.testing.assert_array_almost_equal( metric_pos, convert_arr_pixel_to_metric(pixel_pos, cpar)) def test_brown_affine_types(self): # Assert TypeError is raised when passing a non (n,2) shaped numpy ndarray with self.assertRaises(TypeError): list = [[0 for x in range(2)] for x in range(10) ] # initialize a 10x2 list (but not numpy matrix) correct_arr_brown_affine(list, self.calibration, out=None) with self.assertRaises(TypeError): correct_arr_brown_affine(np.empty((10, 3)), self.calibration, out=None) with self.assertRaises(TypeError): distort_arr_brown_affine(np.empty((2, 1)), self.calibration, out=None) with self.assertRaises(TypeError): distort_arr_brown_affine(np.zeros((11, 2)), self.calibration, out=np.zeros((12, 2))) def test_brown_affine_regress(self): input = np.full((3, 2), 100.) output = np.zeros((3, 2)) correct_output_corr = [[100., 100.], [100., 100.], [100., 100.]] correct_output_dist = [[100., 100.], [100., 100.], [100., 100.]] # Test when passing an array for output correct_arr_brown_affine(input, self.calibration, out=output) np.testing.assert_array_almost_equal(output, correct_output_corr, decimal=7) output = np.zeros((3, 2)) distort_arr_brown_affine(input, self.calibration, out=output) np.testing.assert_array_almost_equal(output, correct_output_dist, decimal=7) # Test when NOT passing an array for output output = correct_arr_brown_affine(input, self.calibration, out=None) np.testing.assert_array_almost_equal(output, correct_output_corr, decimal=7) output = np.zeros((3, 2)) output = distort_arr_brown_affine(input, self.calibration, out=None) np.testing.assert_array_almost_equal(output, correct_output_dist, decimal=7) 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))) 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)
class Test_transforms(unittest.TestCase): def setUp(self): self.input_control_par_file_name = b"testing_fodder/control_parameters/control.par" self.control = ControlParams(4) self.control.read_control_par(self.input_control_par_file_name) 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.calibration = Calibration() self.calibration.from_file(self.input_ori_file_name, self.input_add_file_name) def test_transforms_typecheck(self): """Transform bindings check types""" # Assert TypeError is raised when passing a non (n,2) shaped numpy ndarray with self.assertRaises(TypeError): list = [[0 for x in range(2)] for x in range(10)] # initialize a 10x2 list (but not numpy matrix) convert_arr_pixel_to_metric(list, self.control, out=None) with self.assertRaises(TypeError): convert_arr_pixel_to_metric(np.empty((10, 3)), self.control, out=None) with self.assertRaises(TypeError): convert_arr_metric_to_pixel(np.empty((2, 1)), self.control, out=None) with self.assertRaises(TypeError): convert_arr_metric_to_pixel(np.zeros((11, 2)), self.control, out=np.zeros((12, 2))) def test_transforms_regress(self): """Transformed values are as before.""" input = np.full((3, 2), 100.) output = np.zeros((3, 2)) correct_output_pixel_to_metric = [[-8181. , 6657.92], [-8181. , 6657.92], [-8181. , 6657.92]] correct_output_metric_to_pixel= [[ 646.60066007, 505.81188119], [ 646.60066007, 505.81188119], [ 646.60066007, 505.81188119]] # Test when passing an array for output convert_arr_pixel_to_metric(input, self.control, out=output) np.testing.assert_array_almost_equal(output, correct_output_pixel_to_metric,decimal=7) output = np.zeros((3, 2)) convert_arr_metric_to_pixel(input, self.control, out=output) np.testing.assert_array_almost_equal(output, correct_output_metric_to_pixel, decimal=7) # Test when NOT passing an array for output output=convert_arr_pixel_to_metric(input, self.control, out=None) np.testing.assert_array_almost_equal(output, correct_output_pixel_to_metric,decimal=7) output = np.zeros((3, 2)) output=convert_arr_metric_to_pixel(input, self.control, out=None) np.testing.assert_array_almost_equal(output, correct_output_metric_to_pixel, decimal=7) def test_transforms(self): """Transform in well-known setup gives precalculates results.""" cpar = ControlParams(1) cpar.set_image_size((1280, 1000)) cpar.set_pixel_size((0.1, 0.1)) metric_pos = np.array([ [1., 1.], [-10., 15.], [20., -30.] ]) pixel_pos = np.array([ [650., 490.], [540., 350.], [840., 800.] ]) np.testing.assert_array_almost_equal(pixel_pos, convert_arr_metric_to_pixel(metric_pos, cpar)) np.testing.assert_array_almost_equal(metric_pos, convert_arr_pixel_to_metric(pixel_pos, cpar)) def test_brown_affine_types(self): # Assert TypeError is raised when passing a non (n,2) shaped numpy ndarray with self.assertRaises(TypeError): list = [[0 for x in range(2)] for x in range(10)] # initialize a 10x2 list (but not numpy matrix) correct_arr_brown_affine(list, self.calibration, out=None) with self.assertRaises(TypeError): correct_arr_brown_affine(np.empty((10, 3)), self.calibration, out=None) with self.assertRaises(TypeError): distort_arr_brown_affine(np.empty((2, 1)), self.calibration, out=None) with self.assertRaises(TypeError): distort_arr_brown_affine(np.zeros((11, 2)), self.calibration, out=np.zeros((12, 2))) def test_brown_affine_regress(self): input = np.full((3, 2), 100.) output = np.zeros((3, 2)) correct_output_corr = [[ 100., 100.], [ 100., 100.], [ 100., 100.]] correct_output_dist= [[ 100., 100.], [ 100., 100.], [ 100., 100.]] # Test when passing an array for output correct_arr_brown_affine(input, self.calibration, out=output) np.testing.assert_array_almost_equal(output, correct_output_corr,decimal=7) output = np.zeros((3, 2)) distort_arr_brown_affine(input, self.calibration, out=output) np.testing.assert_array_almost_equal(output, correct_output_dist, decimal=7) # Test when NOT passing an array for output output=correct_arr_brown_affine(input, self.calibration, out=None) np.testing.assert_array_almost_equal(output, correct_output_corr,decimal=7) output = np.zeros((3, 2)) output=distort_arr_brown_affine(input, self.calibration, out=None) np.testing.assert_array_almost_equal(output, correct_output_dist, decimal=7) 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))) 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_point_positions(self): """Point positions""" # prepare MultimediaParams mult_params = self.control.get_multimedia_params() mult_params.set_n1(1.) mult_params.set_layers(np.array([1.]), np.array([1.])) mult_params.set_n3(1.) # 3d point points = np.array([[17, 42, 0], [17, 42, 0]], dtype=float) num_cams = 4 ori_tmpl = r'testing_fodder/calibration/sym_cam{cam_num}.tif.ori' add_file = r'testing_fodder/calibration/cam1.tif.addpar' calibs = [] targs_plain = [] targs_jigged = [] jigg_amp = 0.5 # read calibration for each camera from files for cam in range(num_cams): ori_name = ori_tmpl.format(cam_num=cam + 1) new_cal = Calibration() new_cal.from_file(ori_file=ori_name, add_file=add_file) calibs.append(new_cal) for cam_num, cam_cal in enumerate(calibs): new_plain_targ = image_coordinates( points, cam_cal, self.control.get_multimedia_params()) targs_plain.append(new_plain_targ) if (cam_num % 2) == 0: jigged_points = points - np.r_[0, jigg_amp, 0] else: jigged_points = points + np.r_[0, jigg_amp, 0] new_jigged_targs = image_coordinates( jigged_points, cam_cal, self.control.get_multimedia_params()) targs_jigged.append(new_jigged_targs) targs_plain = np.array(targs_plain).transpose(1,0,2) targs_jigged = np.array(targs_jigged).transpose(1,0,2) skew_dist_plain = point_positions(targs_plain, self.control, calibs) skew_dist_jigged = point_positions(targs_jigged, self.control, calibs) if np.any(skew_dist_plain[1] > 1e-10): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_plain[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_plain[0], axis=1) > 1e-6): self.fail('Rays converge on wrong position.') if np.any(skew_dist_jigged[1] > 0.7): self.fail(('skew distance of target#{targ_num} ' \ + 'is more than allowed').format( targ_num=np.nonzero(skew_dist_jigged[1] > 1e-10)[0][0])) if np.any(np.linalg.norm(points - skew_dist_jigged[0], axis=1) > 0.1): self.fail('Rays converge on wrong position after jigging.')
def run_batch(new_seq_first, new_seq_last): """ this file runs inside exp_path, so the other names are prescribed by the OpenPTV type of a folder: /parameters /img /cal /res """ # read the number of cameras with open('parameters/ptv.par', 'r') as f: n_cams = int(f.readline()) # Control parameters cpar = ControlParams(n_cams) cpar.read_control_par(b'parameters/ptv.par') # Sequence parameters spar = SequenceParams(num_cams=n_cams) spar.read_sequence_par(b'parameters/sequence.par', n_cams) spar.set_first(new_seq_first) spar.set_last(new_seq_last) # Volume parameters vpar = VolumeParams() vpar.read_volume_par(b'parameters/criteria.par') # Tracking parameters track_par = TrackingParams() track_par.read_track_par(b'parameters/track.par') # Target parameters tpar = TargetParams() tpar.read(b'parameters/targ_rec.par') # # Calibration parameters cals = [] for i_cam in range(n_cams): cal = Calibration() tmp = cpar.get_cal_img_base_name(i_cam) cal.from_file(tmp + b'.ori', tmp + b'.addpar') cals.append(cal) # sequence loop for all frames for frame in range(new_seq_first, new_seq_last + 1): print("processing frame %d" % frame) detections = [] corrected = [] for i_cam in range(n_cams): imname = spar.get_img_base_name(i_cam) + str(frame) img = imread(imname) hp = simple_highpass(img, cpar) targs = target_recognition(hp, tpar, i_cam, cpar) print(targs) targs.sort_y() detections.append(targs) mc = MatchedCoords(targs, cpar, cals[i_cam]) pos, pnr = mc.as_arrays() print(i_cam) corrected.append(mc) # if any([len(det) == 0 for det in detections]): # return False # Corresp. + positions. sorted_pos, sorted_corresp, num_targs = correspondences( detections, corrected, cals, vpar, cpar) # Save targets only after they've been modified: for i_cam in xrange(n_cams): detections[i_cam].write(spar.get_img_base_name(i_cam), frame) print("Frame " + str(frame) + " had " \ + repr([s.shape[1] for s in sorted_pos]) + " correspondences.") # Distinction between quad/trip irrelevant here. sorted_pos = np.concatenate(sorted_pos, axis=1) sorted_corresp = np.concatenate(sorted_corresp, axis=1) flat = np.array([corrected[i].get_by_pnrs(sorted_corresp[i]) \ for i in xrange(len(cals))]) pos, rcm = point_positions(flat.transpose(1, 0, 2), cpar, cals, vpar) if len(cals) < 4: print_corresp = -1 * np.ones((4, sorted_corresp.shape[1])) print_corresp[:len(cals), :] = sorted_corresp else: print_corresp = sorted_corresp # Save rt_is rt_is = open(default_naming['corres'] + '.' + str(frame), 'w') rt_is.write(str(pos.shape[0]) + '\n') for pix, pt in enumerate(pos): pt_args = (pix + 1, ) + tuple(pt) + tuple(print_corresp[:, pix]) rt_is.write("%4d %9.3f %9.3f %9.3f %4d %4d %4d %4d\n" % pt_args) rt_is.close() # end of a sequence loop tracker = Tracker(cpar, vpar, track_par, spar, cals, default_naming) tracker.full_forward()
num_cams = 3 num_frames = 5 velocity = 0.01 part_traject = np.zeros((num_frames,3)) part_traject[:,0] = np.r_[:num_frames]*velocity # Find targets on each camera. cpar = ControlParams(3) cpar.read_control_par("testing_fodder/track/parameters/control_newpart.par") targs = [] for cam in xrange(num_cams): cal = Calibration() cal.from_file( "testing_fodder/cal/sym_cam%d.tif.ori" % (cam + 1), "testing_fodder/cal/cam1.tif.addpar") targs.append(convert_arr_metric_to_pixel(image_coordinates( part_traject, cal, cpar.get_multimedia_params()), cpar)) for frame in xrange(num_frames): # write 3D positions: with open("testing_fodder/track/res_orig/particles.%d" % (frame + 1), "w") as outfile: # Note correspondence to the single target in each frame. outfile.writelines([ str(1) + "\n", "{:5d}{:10.3f}{:10.3f}{:10.3f}{:5d}{:5d}{:5d}{:5d}\n".format( 1, part_traject[frame,0], part_traject[frame,1], part_traject[frame,1], 0, 0, 0, 0)]) # write associated targets from all cameras:
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)
num_cams = 3 num_frames = 5 velocity = 0.01 part_traject = np.zeros((num_frames, 3)) part_traject[:, 0] = np.r_[:num_frames] * velocity # Find targets on each camera. cpar = ControlParams(3) cpar.read_control_par("testing_fodder/track/parameters/control_newpart.par") targs = [] for cam in xrange(num_cams): cal = Calibration() cal.from_file("testing_fodder/cal/sym_cam%d.tif.ori" % (cam + 1), "testing_fodder/cal/cam1.tif.addpar") targs.append( convert_arr_metric_to_pixel( image_coordinates(part_traject, cal, cpar.get_multimedia_params()), cpar)) for frame in xrange(num_frames): # write 3D positions: with open("testing_fodder/track/res_orig/particles.%d" % (frame + 1), "w") as outfile: # Note correspondence to the single target in each frame. outfile.writelines([ str(1) + "\n", "{:5d}{:10.3f}{:10.3f}{:10.3f}{:5d}{:5d}{:5d}{:5d}\n".format( 1, part_traject[frame, 0], part_traject[frame, 1], part_traject[frame, 1], 0, 0, 0, 0)