def tps_rpm_bootstrap(x_nd, y_md, z_kd, xy_corr, n_init_iter = 10, n_iter = 20, reg_init = .1, reg_final = .001, rad_init = .1, rad_final = .005, rot_reg = 1e-3, plotting = False, plot_cb = None, old_xyz=None, new_xyz=None): """ modification for tps_rpm in order to use bootstrapping info return a warp taking x to z, proceeds by warping y->z, then intializes tps_rpm with the correspondences from that warping """ _, _, yz_corr = tps_rpm_bij(y_md, z_kd, n_iter = n_iter, reg_init = reg_init, reg_final = reg_final, rad_init = rad_init, rad_final = rad_final, rot_reg = rot_reg, plotting=plotting, plot_cb = plot_cb, old_xyz = old_xyz, new_xyz = new_xyz, return_corr = True) xz_corr = xy_corr.dot(yz_corr) # corr_nk, r_N, _ = balance_matrix3(xz_corr, 10, 1e-1, 1e-2) # corr_nk += 1e-9 corr_nk = xz_corr wt_n = corr_nk.sum(axis=1) wt_k = corr_nk.sum(axis=0) xtarg_nd = (corr_nk/wt_n[:,None]).dot(z_kd) ztarg_kd = (corr_nk/wt_k[None,:]).T.dot(x_nd) f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = reg_final, wt_n=wt_n, rot_coef = rot_reg) g = fit_ThinPlateSpline(z_kd, ztarg_kd, bend_coef = reg_final, wt_n=wt_k, rot_coef = rot_reg) f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, reg_final, wt_n=wt_n)/wt_n.mean() g._cost = tps.tps_cost(g.lin_ag, g.trans_g, g.w_ng, g.x_na, ztarg_kd, reg_final, wt_n=wt_k)/wt_k.mean() print 'cost:\t', f._cost + g._cost return (f, g, corr_nk)
def tps_rpm_bij_presolve(x_nd, y_md, fsolve, gsolve,n_iter = 20, reg_init = .1, reg_final = .001, rad_init = .1, rad_final = .005, rot_reg = 1e-3, outlierprior=1e-1, outlierfrac=2e-1, vis_cost_xy=None, return_corr=False, check_solver=False): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations """ _,d=x_nd.shape regs = np.around(loglinspace(reg_init, reg_final, n_iter), BEND_COEF_DIGITS) rads = loglinspace(rad_init, rad_final, n_iter) f = ThinPlateSpline(d) f.trans_g = np.median(y_md,axis=0) - np.median(x_nd,axis=0) g = ThinPlateSpline(d) g.trans_g = -f.trans_g # r_N = None for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) fwddist_nm = ssd.cdist(xwarped_nd, y_md,'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md,'euclidean') r = rads[i] prob_nm = np.exp( -(fwddist_nm + invdist_nm) / (2*r) ) corr_nm, r_N, _ = balance_matrix3(prob_nm, 10, outlierprior, outlierfrac) corr_nm += 1e-9 wt_n = corr_nm.sum(axis=1) wt_m = corr_nm.sum(axis=0) xtarg_nd = (corr_nm/wt_n[:,None]).dot(y_md) ytarg_md = (corr_nm/wt_m[None,:]).T.dot(x_nd) fsolve.solve(wt_n, xtarg_nd, regs[i], rot_reg, f) gsolve.solve(wt_m, ytarg_md, regs[i], rot_reg, g) if check_solver: f_test = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = regs[i], wt_n=wt_n, rot_coef = rot_reg) g_test = fit_ThinPlateSpline(y_md, ytarg_md, bend_coef = regs[i], wt_n=wt_m, rot_coef = rot_reg) tol = 1e-4 assert np.allclose(f.trans_g, f_test.trans_g, atol=tol) assert np.allclose(f.lin_ag, f_test.lin_ag, atol=tol) assert np.allclose(f.w_ng, f_test.w_ng, atol=tol) assert np.allclose(g.trans_g, g_test.trans_g, atol=tol) assert np.allclose(g.lin_ag, g_test.lin_ag, atol=tol) assert np.allclose(g.w_ng, g_test.w_ng, atol=tol) f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, regs[i], wt_n=wt_n)/wt_n.mean() g._cost = tps.tps_cost(g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, regs[i], wt_n=wt_m)/wt_m.mean() if return_corr: return (f, g), corr_nm return f,g
def tps_rpm_bij(x_nd, y_md, n_iter = 20, reg_init = .1, reg_final = .001, rad_init = .1, rad_final = .005, rot_reg = 1e-3): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations """ _,d=x_nd.shape regs = loglinspace(reg_init, reg_final, n_iter) rads = loglinspace(rad_init, rad_final, n_iter) if not f_init: f = ThinPlateSpline(d) f.trans_g = np.median(y_md,axis=0) - np.median(x_nd,axis=0) else: f = f_init if not f_init: g = ThinPlateSpline(d) g.trans_g = -f.trans_g else: g = g_init # r_N = None for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) fwddist_nm = ssd.cdist(xwarped_nd, y_md,'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md,'euclidean') r = rads[i] prob_nm = np.exp( -(fwddist_nm + invdist_nm) / (2*r) ) corr_nm, r_N, _ = balance_matrix3(prob_nm, 10, 1e-1, 1e-2) corr_nm += 1e-9 wt_n = corr_nm.sum(axis=1) wt_m = corr_nm.sum(axis=0) inlier = wt_n > 1e-2 xtarg_nd = np.empty(x_nd.shape) xtarg_nd[inlier, :] = (corr_nm/wt_n[:,None]).dot(y_md)[inlier, :] xtarg_nd[~inlier, :] = xwarped_nd[~inlier, :] inlier = wt_m > 1e-2 ytarg_md = np.empty(y_md.shape) ytarg_md[inlier, :] = (corr_nm/wt_m[:,None]).dot(y_md)[inlier, :] ytarg_md[~inlier, :] = ywarped_md[~inlier, :] f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = regs[i], wt_n=wt_n, rot_coef = rot_reg) g = fit_ThinPlateSpline(y_md, ytarg_md, bend_coef = regs[i], wt_n=wt_m, rot_coef = rot_reg) f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, regs[i], wt_n=wt_n)/wt_n.mean() g._cost = tps.tps_cost(g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, regs[i], wt_n=wt_m)/wt_m.mean() if return_corr: return f, g, corr_nm return f,g
def fit_ThinPlateSpline_corr(x_nd, y_md, corr_nm, l, rot_reg, x_weights = None): wt_n = corr_nm.sum(axis=1) if np.any(wt_n == 0): inlier = wt_n != 0 x_nd = x_nd[inlier,:] wt_n = wt_n[inlier,:] x_weights = x_weights[inlier] xtarg_nd = (corr_nm[inlier,:]/wt_n[:,None]).dot(y_md) else: xtarg_nd = (corr_nm/wt_n[:,None]).dot(y_md) if x_weights is not None: if x_weights.ndim > 1: wt_n=wt_n[:,None]*x_weights else: wt_n=wt_n*x_weights f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = l, wt_n = wt_n, rot_coef = rot_reg) f._bend_coef = l f._wt_n = wt_n f._rot_coef = rot_reg f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, l, wt_n=wt_n)/wt_n.mean() return f
def rpm_em_step_stat(x_nd, y_md, l, T, rot_reg, prev_f, vis_cost_xy = None, outlierprior = 1e-2, normalize_iter = 20, T0 = .04, user_data=None): """ Statiscal interpretation of the RPM EM step """ n,d = x_nd.shape m,_ = y_md.shape xwarped_nd = prev_f.transform_points(x_nd) dist_nm = ssd.cdist(xwarped_nd, y_md, 'sqeuclidean') outlier_dist_1m = ssd.cdist(xwarped_nd.mean(axis=0)[None,:], y_md, 'sqeuclidean') outlier_dist_n1 = ssd.cdist(xwarped_nd, y_md.mean(axis=0)[None,:], 'sqeuclidean') # Note: proportionality constants within a column can be ignored since Sinkorn balancing normalizes the columns first prob_nm = np.exp( -(dist_nm / (2*T)) + (outlier_dist_1m / (2*T0)) ) / np.sqrt(T) # divide by np.exp( outlier_dist_1m / (2*T0) ) to prevent prob collapsing to zero if vis_cost_xy != None: pi = np.exp( -vis_cost_xy ) pi /= pi.sum(axis=0)[None,:] # normalize along columns; these are proper probabilities over j = 1,...,N prob_nm *= (1. - outlierprior) * pi else: prob_nm *= (1. - outlierprior) / float(n) outlier_prob_1m = outlierprior * np.ones((1,m)) / np.sqrt(T0) # divide by np.exp( outlier_dist_1m / (2*T0) ) outlier_prob_n1 = np.exp( -outlier_dist_n1 / (2*T0) ) / np.sqrt(T0) prob_NM = np.empty((n+1, m+1), 'f4') prob_NM[:n, :m] = prob_nm prob_NM[:n, m][:,None] = outlier_prob_n1 prob_NM[n, :m][None,:] = outlier_prob_1m prob_NM[n, m] = 0 r_N, c_M = sinkhorn_balance_coeffs(prob_NM, normalize_iter) prob_NM *= r_N[:,None] prob_NM *= c_M[None,:] # prob_NM needs to be row-normalized at this point corr_nm = prob_NM[:n, :m] wt_n = corr_nm.sum(axis=1) # discard points that are outliers (i.e. their total correspondence is smaller than 1e-2) inlier = wt_n > 1e-2 if np.any(~inlier): x_nd = x_nd[inlier,:] wt_n = wt_n[inlier,:] xtarg_nd = (corr_nm[inlier,:]/wt_n[:,None]).dot(y_md) else: xtarg_nd = (corr_nm/wt_n[:,None]).dot(y_md) f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = l, wt_n = wt_n, rot_coef = rot_reg) f._bend_coef = l f._rot_coef = rot_reg f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, l, wt_n=wt_n)/wt_n.mean() return f, corr_nm
def tps_rpm(x_nd, y_md, n_iter = 5, reg_init = .1, reg_final = .001, rad_init = .2, rad_final = .001, plotting = False, verbose=True, f_init = None, return_full = False, plot_cb = None): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations """ n,d = x_nd.shape regs = loglinspace(reg_init, reg_final, n_iter) rads = loglinspace(rad_init, rad_final, n_iter) if f_init is not None: f = f_init else: f = ThinPlateSpline(d) f.trans_g = np.median(y_md,axis=0) - np.median(x_nd,axis=0) if plot_cb is None: plot_cb = default_plot_callback for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) # targ_nd = find_targets(x_nd, y_md, corr_opts = dict(r = rads[i], p = .1)) corr_nm = calc_correspondence_matrix(xwarped_nd, y_md, r=rads[i], p=.2) wt_n = corr_nm.sum(axis=1) goodn = wt_n > .1 targ_Nd = np.dot(corr_nm[goodn, :]/wt_n[goodn][:,None], y_md) if plotting and i%plotting==0: plot_cb(x_nd, y_md, targ_Nd, corr_nm, wt_n, f) x_Nd = x_nd[goodn] f.fit(x_Nd, targ_Nd, bend_coef = regs[i], wt_n = wt_n[goodn], rot_coef = 10*regs[i], verbose=verbose) if return_full: info = {} info["corr_nm"] = corr_nm info["goodn"] = goodn info["x_Nd"] = x_nd[goodn,:] info["targ_Nd"] = targ_Nd info["wt_N"] = wt_n[goodn] info["cost"] = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, x_Nd, targ_Nd, regs[-1]) return f, info else: return f
def tps_rpm_bij(x_nd, y_md, n_iter=20, reg_init=.1, reg_final=.001, rad_init=.1, rad_final=.005, rot_reg=1e-3, plotting=False, plot_cb=None, x_weights=None, y_weights=None, outlierprior=.1, outlierfrac=2e-1, vis_cost_xy=None, return_corr=False): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations interest_pts are points in either scene where we want a lower prior of outliers x_weights: rescales the weights of the forward tps fitting of the last iteration y_weights: same as x_weights, but for the backward tps fitting """ _, d = x_nd.shape regs = loglinspace(reg_init, reg_final, n_iter) rads = loglinspace(rad_init, rad_final, n_iter) f = ThinPlateSpline(d) scale = (np.max(y_md, axis=0) - np.min(y_md, axis=0)) / ( np.max(x_nd, axis=0) - np.min(x_nd, axis=0)) f.lin_ag = np.diag(scale) # align the mins and max f.trans_g = np.median( y_md, axis=0) - np.median(x_nd, axis=0) * scale # align the medians # do a coarse search through rotations # fit_rotation(f, x_nd, y_md) g = ThinPlateSpline(d) g.lin_ag = np.diag(1. / scale) g.trans_g = -np.diag(1. / scale).dot(f.trans_g) # set up outlier priors for source and target scenes n, _ = x_nd.shape m, _ = y_md.shape x_priors = np.ones(n) * outlierprior y_priors = np.ones(m) * outlierprior # r_N = None for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) fwddist_nm = ssd.cdist(xwarped_nd, y_md, 'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md, 'euclidean') r = rads[i] prob_nm = np.exp(-(fwddist_nm + invdist_nm) / (2 * r)) if vis_cost_xy != None: pi = np.exp(-vis_cost_xy) pi /= pi.max( ) # rescale the maximum probability to be 1. effectively, the outlier priors are multiplied by a # visual prior of 1 (since the outlier points have a visual prior of 1 with any point) prob_nm *= pi corr_nm, r_N, _ = balance_matrix3( prob_nm, 10, x_priors, y_priors, outlierfrac) # edit final value to change outlier percentage corr_nm += 1e-9 wt_n = corr_nm.sum(axis=1) wt_m = corr_nm.sum(axis=0) xtarg_nd = (corr_nm / wt_n[:, None]).dot(y_md) ytarg_md = (corr_nm / wt_m[None, :]).T.dot(x_nd) if plotting and i % plotting == 0: plot_cb(x_nd, y_md, xtarg_nd, corr_nm, wt_n, f) if i == (n_iter - 1): if x_weights is not None: wt_n = wt_n * x_weights if y_weights is not None: wt_m = wt_m * y_weights f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef=regs[i], wt_n=wt_n, rot_coef=rot_reg) g = fit_ThinPlateSpline(y_md, ytarg_md, bend_coef=regs[i], wt_n=wt_m, rot_coef=rot_reg) f._cost = tps_cost( f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, regs[i], wt_n=wt_n) / wt_n.mean() g._cost = tps_cost( g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, regs[i], wt_n=wt_m) / wt_m.mean() if return_corr: return (f, g), corr_nm return f, g
def tps_rpm_bij(x_nd, y_md, n_iter=20, reg_init=.1, reg_final=.001, rad_init=.1, rad_final=.005, rot_reg = 1e-3, plotting = False, plot_cb = None, x_weights = None, y_weights = None, outlierprior = .1, outlierfrac = 2e-1, vis_cost_xy = None, return_corr=False): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations interest_pts are points in either scene where we want a lower prior of outliers x_weights: rescales the weights of the forward tps fitting of the last iteration y_weights: same as x_weights, but for the backward tps fitting """ _,d=x_nd.shape regs = loglinspace(reg_init, reg_final, n_iter) rads = loglinspace(rad_init, rad_final, n_iter) f = ThinPlateSpline(d) scale = (np.max(y_md,axis=0) - np.min(y_md,axis=0)) / (np.max(x_nd,axis=0) - np.min(x_nd,axis=0)) f.lin_ag = np.diag(scale) # align the mins and max f.trans_g = np.median(y_md,axis=0) - np.median(x_nd,axis=0) * scale # align the medians # do a coarse search through rotations # fit_rotation(f, x_nd, y_md) g = ThinPlateSpline(d) g.lin_ag = np.diag(1./scale) g.trans_g = -np.diag(1./scale).dot(f.trans_g) # set up outlier priors for source and target scenes n, _ = x_nd.shape m, _ = y_md.shape x_priors = np.ones(n)*outlierprior y_priors = np.ones(m)*outlierprior # r_N = None for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) fwddist_nm = ssd.cdist(xwarped_nd, y_md,'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md,'euclidean') r = rads[i] prob_nm = np.exp( -(fwddist_nm + invdist_nm) / (2*r) ) if vis_cost_xy != None: pi = np.exp( -vis_cost_xy ) pi /= pi.max() # rescale the maximum probability to be 1. effectively, the outlier priors are multiplied by a # visual prior of 1 (since the outlier points have a visual prior of 1 with any point) prob_nm *= pi corr_nm, r_N, _ = balance_matrix3(prob_nm, 10, x_priors, y_priors, outlierfrac) # edit final value to change outlier percentage corr_nm += 1e-9 wt_n = corr_nm.sum(axis=1) wt_m = corr_nm.sum(axis=0) xtarg_nd = (corr_nm/wt_n[:,None]).dot(y_md) ytarg_md = (corr_nm/wt_m[None,:]).T.dot(x_nd) if plotting and i%plotting==0: plot_cb(x_nd, y_md, xtarg_nd, corr_nm, wt_n, f) if i == (n_iter-1): if x_weights is not None: wt_n=wt_n*x_weights if y_weights is not None: wt_m=wt_m*y_weights f = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef = regs[i], wt_n=wt_n, rot_coef = rot_reg) g = fit_ThinPlateSpline(y_md, ytarg_md, bend_coef = regs[i], wt_n=wt_m, rot_coef = rot_reg) f._cost = tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, regs[i], wt_n=wt_n)/wt_n.mean() g._cost = tps_cost(g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, regs[i], wt_n=wt_m)/wt_m.mean() if return_corr: return (f, g), corr_nm return f,g
def tps_rpm(x_nd, y_md, n_iter=5, reg_init=.1, reg_final=.001, rad_init=.2, rad_final=.001, plotting=False, verbose=True, f_init=None, return_full=False, plot_cb=None): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations """ n, d = x_nd.shape regs = loglinspace(reg_init, reg_final, n_iter) rads = loglinspace(rad_init, rad_final, n_iter) if f_init is not None: f = f_init else: f = ThinPlateSpline(d) f.trans_g = np.median(y_md, axis=0) - np.median(x_nd, axis=0) if plot_cb is None: plot_cb = default_plot_callback for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) # targ_nd = find_targets(x_nd, y_md, corr_opts = dict(r = rads[i], p = .1)) corr_nm = calc_correspondence_matrix(xwarped_nd, y_md, r=rads[i], p=.2) wt_n = corr_nm.sum(axis=1) goodn = wt_n > .1 targ_Nd = np.dot(corr_nm[goodn, :] / wt_n[goodn][:, None], y_md) if plotting and i % plotting == 0: plot_cb(x_nd, y_md, targ_Nd, corr_nm, wt_n, f) x_Nd = x_nd[goodn] f.fit(x_Nd, targ_Nd, bend_coef=regs[i], wt_n=wt_n[goodn], rot_coef=10 * regs[i], verbose=verbose) if return_full: info = {} info["corr_nm"] = corr_nm info["goodn"] = goodn info["x_Nd"] = x_nd[goodn, :] info["targ_Nd"] = targ_Nd info["wt_N"] = wt_n[goodn] info["cost"] = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, x_Nd, targ_Nd, regs[-1]) return f, info else: return f
def tps_rpm_bij(x_nd, y_md, fsolve, gsolve, n_iter=20, reg_init=.1, reg_final=.001, rad_init=.1, rad_final=.005, rot_reg=1e-3, outlierprior=1e-1, outlierfrac=2e-1, vis_cost_xy=None, return_corr=False, check_solver=False): """ tps-rpm algorithm mostly as described by chui and rangaran reg_init/reg_final: regularization on curvature rad_init/rad_final: radius for correspondence calculation (meters) plotting: 0 means don't plot. integer n means plot every n iterations """ _, d = x_nd.shape regs = np.around(loglinspace(reg_init, reg_final, n_iter), BEND_COEF_DIGITS) rads = loglinspace(rad_init, rad_final, n_iter) f = ThinPlateSpline(d) scale = (np.max(y_md, axis=0) - np.min(y_md, axis=0)) / ( np.max(x_nd, axis=0) - np.min(x_nd, axis=0)) f.lin_ag = np.diag(scale) # align the mins and max f.trans_g = np.median( y_md, axis=0) - np.median(x_nd, axis=0) * scale # align the medians g = ThinPlateSpline(d) g.lin_ag = np.diag(1. / scale) g.trans_g = -np.diag(1. / scale).dot(f.trans_g) # r_N = None for i in xrange(n_iter): xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) fwddist_nm = ssd.cdist(xwarped_nd, y_md, 'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md, 'euclidean') r = rads[i] prob_nm = np.exp(-(fwddist_nm + invdist_nm) / (2 * r)) corr_nm, r_N, _ = balance_matrix(prob_nm, 10, outlierprior, outlierfrac) corr_nm += 1e-9 wt_n = corr_nm.sum(axis=1) wt_m = corr_nm.sum(axis=0) xtarg_nd = (corr_nm / wt_n[:, None]).dot(y_md) ytarg_md = (corr_nm / wt_m[None, :]).T.dot(x_nd) fsolve.solve(wt_n, xtarg_nd, regs[i], rot_reg, f) gsolve.solve(wt_m, ytarg_md, regs[i], rot_reg, g) if check_solver: f_test = fit_ThinPlateSpline(x_nd, xtarg_nd, bend_coef=regs[i], wt_n=wt_n, rot_coef=rot_reg) g_test = fit_ThinPlateSpline(y_md, ytarg_md, bend_coef=regs[i], wt_n=wt_m, rot_coef=rot_reg) tol = 1e-4 assert np.allclose(f.trans_g, f_test.trans_g, atol=tol) assert np.allclose(f.lin_ag, f_test.lin_ag, atol=tol) assert np.allclose(f.w_ng, f_test.w_ng, atol=tol) assert np.allclose(g.trans_g, g_test.trans_g, atol=tol) assert np.allclose(g.lin_ag, g_test.lin_ag, atol=tol) assert np.allclose(g.w_ng, g_test.w_ng, atol=tol) f._cost = tps.tps_cost( f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, regs[i], wt_n=wt_n) / wt_n.mean() g._cost = tps.tps_cost( g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, regs[i], wt_n=wt_m) / wt_m.mean() if return_corr: return (f, g), corr_nm return f, g
def test_batch_tps_rpm_bij(src_ctx, tgt_ctx, T_init = 1e-1, T_final = 5e-3, outlierfrac = 1e-2, outlierprior = 1e-1, outliercutoff = .5, em_iter = EM_ITER_CHEAP, test_ind = 0): from transformations import ThinPlateSpline, set_ThinPlateSpline import tps n_iter = len(src_ctx.bend_coefs) T_vals = loglinspace(T_init, T_final, n_iter) x_nd = src_ctx.pts[test_ind].get()[:src_ctx.dims[test_ind]] y_md = tgt_ctx.pts[0].get()[:tgt_ctx.dims[0]] (n, d) = x_nd.shape (m, _) = y_md.shape f = ThinPlateSpline(d) g = ThinPlateSpline(d) src_ctx.reset_tps_params() tgt_ctx.reset_tps_params() for i, b in enumerate(src_ctx.bend_coefs): T = T_vals[i] for _ in range(em_iter): src_ctx.transform_points() tgt_ctx.transform_points() xwarped_nd = f.transform_points(x_nd) ywarped_md = g.transform_points(y_md) gpu_xw = src_ctx.pts_w[test_ind].get()[:n, :] gpu_yw = tgt_ctx.pts_w[test_ind].get()[:m, :] assert np.allclose(xwarped_nd, gpu_xw, atol=1e-5) assert np.allclose(ywarped_md, gpu_yw, atol=1e-5) xwarped_nd = gpu_xw ywarped_md = gpu_yw src_ctx.get_target_points(tgt_ctx, outlierprior, outlierfrac, outliercutoff, T) fwddist_nm = ssd.cdist(xwarped_nd, y_md,'euclidean') invdist_nm = ssd.cdist(x_nd, ywarped_md,'euclidean') prob_nm = outlierprior * np.ones((n+1, m+1), np.float32) prob_nm[:n, :m] = np.exp( -(fwddist_nm + invdist_nm) / float(2*T)) prob_nm[n, m] = outlierfrac * np.sqrt(n * m) gpu_corr = src_ctx.corr_rm[test_ind].get() gpu_corr = gpu_corr.flatten() gpu_corr = gpu_corr[:(n + 1) * (m + 1)].reshape(n+1, m+1).astype(np.float32) assert np.allclose(prob_nm[:n, :m], gpu_corr[:n, :m], atol=1e-5) prob_nm[:n, :m] = gpu_corr[:n, :m] r_coefs = np.ones(n+1, np.float32) c_coefs = np.ones(m+1, np.float32) a_N = np.ones((n+1),dtype = np.float32) a_N[n] = m*outlierfrac b_M = np.ones((m+1), dtype = np.float32) b_M[m] = n*outlierfrac for _ in range(DEFAULT_NORM_ITERS): r_coefs = a_N/prob_nm.dot(c_coefs) rn_c_coefs = c_coefs c_coefs = b_M/r_coefs.dot(prob_nm) gpu_r_coefs = src_ctx.r_coefs[test_ind].get()[:n+1].reshape(n+1) gpu_c_coefs_cn = src_ctx.c_coefs_cn[test_ind].get()[:m+1].reshape(m+1) gpu_c_coefs_rn = src_ctx.c_coefs_rn[test_ind].get()[:m+1].reshape(m+1) assert np.allclose(r_coefs, gpu_r_coefs, atol=1e-5) assert np.allclose(c_coefs, gpu_c_coefs_cn, atol=1e-5) assert np.allclose(rn_c_coefs, gpu_c_coefs_rn, atol=1e-5) prob_nm = prob_nm[:n, :m] prob_nm *= gpu_r_coefs[:n, None] rn_p_nm = prob_nm * gpu_c_coefs_rn[None, :m] cn_p_nm = prob_nm * gpu_c_coefs_cn[None, :m] wt_n = rn_p_nm.sum(axis=1) gpu_corr_cm = src_ctx.corr_cm[test_ind].get().flatten()[:(n+1)*(m+1)] gpu_corr_cm = gpu_corr_cm.reshape(m+1, n+1)## b/c it is column major assert np.allclose(wt_n, gpu_corr_cm[m, :n], atol=1e-4) inlier = wt_n > outliercutoff xtarg_nd = np.empty((n, DATA_DIM), np.float32) xtarg_nd[inlier, :] = rn_p_nm.dot(y_md)[inlier, :] xtarg_nd[~inlier, :] = xwarped_nd[~inlier, :] wt_m = cn_p_nm.sum(axis=0) assert np.allclose(wt_m, gpu_corr[n, :m], atol=1e-4) inlier = wt_m > outliercutoff ytarg_md = np.empty((m, DATA_DIM), np.float32) ytarg_md[inlier, :] = cn_p_nm.T.dot(x_nd)[inlier, :] ytarg_md[~inlier, :] = ywarped_md[~inlier, :] xt_gpu = src_ctx.pts_t[test_ind].get()[:n, :] yt_gpu = tgt_ctx.pts_t[test_ind].get()[:m, :] assert np.allclose(xtarg_nd, xt_gpu, atol=1e-4) assert np.allclose(ytarg_md, yt_gpu, atol=1e-4) src_ctx.update_transform(b) tgt_ctx.update_transform(b) f_p_mat = src_ctx.proj_mats[b][test_ind].get()[:n+d+1, :n] f_o_mat = src_ctx.offset_mats[b][test_ind].get()[:n+d+1] b_p_mat = tgt_ctx.proj_mats[b][0].get()[:m+d+1, :m] b_o_mat = tgt_ctx.offset_mats[b][0].get()[:m+d+1] f_params = f_p_mat.dot(xtarg_nd) + f_o_mat g_params = b_p_mat.dot(ytarg_md) + b_o_mat gpu_fparams = src_ctx.tps_params[test_ind].get()[:n+d+1] gpu_gparams = tgt_ctx.tps_params[test_ind].get()[:m+d+1] assert np.allclose(f_params, gpu_fparams, atol=1e-4) assert np.allclose(g_params, gpu_gparams, atol=1e-4) set_ThinPlateSpline(f, x_nd, gpu_fparams) set_ThinPlateSpline(g, y_md, gpu_gparams) f._cost = tps.tps_cost(f.lin_ag, f.trans_g, f.w_ng, f.x_na, xtarg_nd, 1) g._cost = tps.tps_cost(g.lin_ag, g.trans_g, g.w_ng, g.x_na, ytarg_md, 1) gpu_cost = src_ctx.bidir_tps_cost(tgt_ctx) cpu_cost = f._cost + g._cost assert np.isclose(gpu_cost[test_ind], cpu_cost, atol=1e-4)