def apply_normalization_to_output_with_gradients(v,dv_dq,dv_di): # vn = v/mag(v) # dvn = dv (1/mag(v)) + v d(1/mag(v)) # = dv( 1/mag(v) - v vt / mag^3(v) ) # = dv( 1/mag(v) - vn vnt / mag(v) ) # = dv/mag(v) ( 1 - vn vnt ) # v has shape (...,3) # dv_dq has shape (...,3,2) # dv_di has shape (...,3,N) # shape (...,1) magv_recip = 1. / nps.dummy(nps.mag(v), -1) v *= magv_recip # shape (...,1,1) magv_recip = nps.dummy(magv_recip,-1) dv_dq *= magv_recip dv_dq -= nps.xchg( nps.matmult( nps.dummy(nps.xchg(dv_dq, -1,-2), -2), nps.dummy(nps.outer(v,v),-3) )[...,0,:], -1, -2) dv_di *= magv_recip dv_di -= nps.xchg( nps.matmult( nps.dummy(nps.xchg(dv_di, -1,-2), -2), nps.dummy(nps.outer(v,v),-3) )[...,0,:], -1, -2)
def _triangulate(# shape (Ncameras, Nintrinsics) intrinsics_data, # shape (Ncameras, 6) rt_cam_ref, # shape (Nframes,6), rt_ref_frame, rt_ref_frame_true, # shape (..., Ncameras, 2) q, lensmodel, stabilize_coords, get_gradients): if not ( intrinsics_data.ndim == 2 and intrinsics_data.shape[0] == 2 and \ rt_cam_ref.shape == (2,6) and \ rt_ref_frame.ndim == 2 and rt_ref_frame.shape[-1] == 6 and \ q.shape[-2:] == (2,2 ) ): raise Exception("Arguments must have a consistent Ncameras == 2") # I now compute the same triangulation, but just at the un-perturbed baseline, # and keeping track of all the gradients rt0r = rt_cam_ref[0] rt1r = rt_cam_ref[1] if not get_gradients: rtr1 = mrcal.invert_rt(rt1r) rt01_baseline = mrcal.compose_rt(rt0r, rtr1) # all the v have shape (...,3) vlocal0 = \ mrcal.unproject(q[...,0,:], lensmodel, intrinsics_data[0]) vlocal1 = \ mrcal.unproject(q[...,1,:], lensmodel, intrinsics_data[1]) v0 = vlocal0 v1 = \ mrcal.rotate_point_r(rt01_baseline[:3], vlocal1) # p_triangulated has shape (..., 3) p_triangulated = \ mrcal.triangulate_leecivera_mid2(v0, v1, rt01_baseline[3:]) if stabilize_coords: # shape (..., Nframes, 3) p_frames_new = \ mrcal.transform_point_rt(mrcal.invert_rt(rt_ref_frame), nps.dummy(p_triangulated,-2)) # shape (..., Nframes, 3) p_refs = mrcal.transform_point_rt(rt_ref_frame_true, p_frames_new) # shape (..., 3) p_triangulated = np.mean(p_refs, axis=-2) return p_triangulated else: rtr1,drtr1_drt1r = mrcal.invert_rt(rt1r, get_gradients=True) rt01_baseline,drt01_drt0r, drt01_drtr1 = mrcal.compose_rt(rt0r, rtr1, get_gradients=True) # all the v have shape (...,3) vlocal0, dvlocal0_dq0, dvlocal0_dintrinsics0 = \ mrcal.unproject(q[...,0,:], lensmodel, intrinsics_data[0], get_gradients = True) vlocal1, dvlocal1_dq1, dvlocal1_dintrinsics1 = \ mrcal.unproject(q[...,1,:], lensmodel, intrinsics_data[1], get_gradients = True) v0 = vlocal0 v1, dv1_dr01, dv1_dvlocal1 = \ mrcal.rotate_point_r(rt01_baseline[:3], vlocal1, get_gradients=True) # p_triangulated has shape (..., 3) p_triangulated, dp_triangulated_dv0, dp_triangulated_dv1, dp_triangulated_dt01 = \ mrcal.triangulate_leecivera_mid2(v0, v1, rt01_baseline[3:], get_gradients = True) shape_leading = dp_triangulated_dv0.shape[:-2] dp_triangulated_dq = np.zeros(shape_leading + (3,) + q.shape[-2:], dtype=float) nps.matmult( dp_triangulated_dv0, dvlocal0_dq0, out = dp_triangulated_dq[..., 0, :]) nps.matmult( dp_triangulated_dv1, dv1_dvlocal1, dvlocal1_dq1, out = dp_triangulated_dq[..., 1, :]) Nframes = len(rt_ref_frame) if stabilize_coords: # shape (Nframes,6) rt_frame_ref, drtfr_drtrf = \ mrcal.invert_rt(rt_ref_frame, get_gradients=True) # shape (Nframes,6) rt_true_shifted, _, drt_drtfr = \ mrcal.compose_rt(rt_ref_frame_true, rt_frame_ref, get_gradients=True) # shape (..., Nframes, 3) p_refs,dprefs_drt,dprefs_dptriangulated = \ mrcal.transform_point_rt(rt_true_shifted, nps.dummy(p_triangulated,-2), get_gradients = True) # shape (..., 3) p_triangulated = np.mean(p_refs, axis=-2) # I have dpold/dx. dpnew/dx = dpnew/dpold dpold/dx # shape (...,3,3) dpnew_dpold = np.mean(dprefs_dptriangulated, axis=-3) dp_triangulated_dv0 = nps.matmult(dpnew_dpold, dp_triangulated_dv0) dp_triangulated_dv1 = nps.matmult(dpnew_dpold, dp_triangulated_dv1) dp_triangulated_dt01 = nps.matmult(dpnew_dpold, dp_triangulated_dt01) dp_triangulated_dq = nps.xchg(nps.matmult( dpnew_dpold, nps.xchg(dp_triangulated_dq, -2,-3)), -2,-3) # shape (..., Nframes,3,6) dp_triangulated_drtrf = \ nps.matmult(dprefs_drt, drt_drtfr, drtfr_drtrf) / Nframes else: dp_triangulated_drtrf = np.zeros(shape_leading + (Nframes,3,6), dtype=float) return \ p_triangulated, \ drtr1_drt1r, \ drt01_drt0r, drt01_drtr1, \ dvlocal0_dintrinsics0, dvlocal1_dintrinsics1, \ dv1_dr01, dv1_dvlocal1, \ dp_triangulated_dv0, dp_triangulated_dv1, dp_triangulated_dt01, \ dp_triangulated_drtrf, \ dp_triangulated_dq
imagersizes, intrinsics_true, extrinsics_true_mounted, frames_true, observations_true, intrinsics_sampled, extrinsics_sampled_mounted, frames_sampled, calobject_warp_sampled) = pickle.load(f) baseline_rt_ref_frame = optimization_inputs_baseline['frames_rt_toref'] icam0, icam1 = args.cameras Rt01_true = mrcal.compose_Rt( mrcal.Rt_from_rt(extrinsics_rt_fromref_true[icam0]), mrcal.invert_Rt(mrcal.Rt_from_rt(extrinsics_rt_fromref_true[icam1]))) Rt10_true = mrcal.invert_Rt(Rt01_true) # shape (Npoints,Ncameras,3) p_triangulated_true_local = nps.xchg( nps.cat(p_triangulated_true0, mrcal.transform_point_Rt(Rt10_true, p_triangulated_true0)), 0, 1) # Pixel coords at the perfect intersection # shape (Npoints,Ncameras,2) q_true = nps.xchg( np.array([ mrcal.project(p_triangulated_true_local[:,i,:], lensmodel, intrinsics_true[args.cameras[i]]) \ for i in range(2)]), 0,1) # Sanity check. Without noise, the triangulation should report the test point exactly p_triangulated0 = \ triangulate_nograd(models_true[icam0].intrinsics()[1], models_true[icam1].intrinsics()[1], models_true[icam0].extrinsics_rt_fromref(),
intrinsics_sampled, extrinsics_sampled_mounted, frames_sampled, calobject_warp_sampled) = pickle.load(f) Npoints = p_triangulated_true.shape[0] Rt01_true = mrcal.compose_Rt(mrcal.Rt_from_rt(extrinsics_rt_fromref_true[0]), mrcal.invert_Rt(mrcal.Rt_from_rt(extrinsics_rt_fromref_true[1]))) Rt10_true = mrcal.invert_Rt(Rt01_true) # shape (Npoints,Ncameras,3) p_triangulated_true_local = nps.xchg( nps.cat( p_triangulated_true, mrcal.transform_point_Rt(Rt10_true, p_triangulated_true) ), 0,1) # Pixel coords at the perfect intersection # shape (Npoints,Ncameras,2) q_true = nps.xchg( np.array([ mrcal.project(p_triangulated_true_local[:,i,:], lensmodel, intrinsics_true[i]) \ for i in range(len(intrinsics_true))]), 0,1) # Let's define the observation-time pixel noise. The noise vector # q_true_sampled_noise has the same shape as q_true for each sample. so # q_true_sampled_noise.shape = (Nsamples,Npoints,Ncameras,2). The covariance is