def compute_data_term_energy_contribution(warped_live_field, canonical_field, band_union_only=True): diff = warped_live_field - canonical_field if band_union_only: set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, diff) data_energy = np.sum(0.5 * diff ** 2) return data_energy
def test_data_term02(self): warped_live_field = np.array([[0.3, 0.4], [-0.8, 1.0]], dtype=np.float32) canonical_field = np.array([[0.5, -0.3], [1.0, -1.0]], dtype=np.float32) live_gradient_y, live_gradient_x = np.gradient(warped_live_field) expected_gradient_out = np.array( [[[-.2, 2.2], [0.7, 4.2]], [[-32.4, 19.8], [0.0, 0.0]]], dtype=np.float32) expected_energy_out = 1.885 data_gradient_out, energy_out = \ dt.compute_data_term_gradient_direct(warped_live_field, canonical_field, live_gradient_x, live_gradient_y) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out, places=6) data_gradient_out = \ dt.compute_data_term_gradient_vectorized(warped_live_field, canonical_field, live_gradient_x, live_gradient_y) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, data_gradient_out) energy_out = dt.compute_data_term_energy_contribution( warped_live_field, canonical_field) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out)
def test_data_term03(self): warped_live_field = np.array( [[1., 1., 0.49999955, 0.42499956], [1., 0.44999936, 0.34999937, 0.32499936], [1., 0.35000065, 0.25000066, 0.22500065], [1., 0.20000044, 0.15000044, 0.07500044]], dtype=np.float32) canonical_field = np.array( [[1.0000000e+00, 1.0000000e+00, 3.7499955e-01, 2.4999955e-01], [1.0000000e+00, 3.2499936e-01, 1.9999936e-01, 1.4999935e-01], [1.0000000e+00, 1.7500064e-01, 1.0000064e-01, 5.0000645e-02], [1.0000000e+00, 7.5000443e-02, 4.4107438e-07, -9.9999562e-02]], dtype=np.float32) live_gradient_y, live_gradient_x = np.gradient(warped_live_field) expected_gradient_out = np.array([[ [0., 0.], [0., 0.], [-0.35937524, -0.18750024], [-0.13125, -0.17500037], ], [ [0., 0.], [-0.4062504, -0.4062496], [-0.09375, -0.1874992], [-0.04375001, -0.17499907], ], [ [0., 0.], [-0.65624946, -0.21874908], [-0.09375, -0.1499992], [-0.04375001, -0.21874908], ], [ [0., 0.], [-0.5312497, -0.18750025], [-0.09374999, -0.15000032], [-0.13125001, -0.2625004], ]], dtype=np.float32) expected_energy_out = 0.13375 data_gradient_out, energy_out = \ dt.compute_data_term_gradient_direct(warped_live_field, canonical_field, live_gradient_x, live_gradient_y) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out) data_gradient_out = \ dt.compute_data_term_gradient_vectorized(warped_live_field, canonical_field, live_gradient_x, live_gradient_y) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, data_gradient_out) energy_out = dt.compute_data_term_energy_contribution( warped_live_field, canonical_field) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out)
def test_smoothing_term04(self): # @formatter:off warp_field = np.array( [0, 0, -0, -0, -0.0338037, -0.0174936, -0.0112804, -0.0191113, -0, 0, -0.0379127, -0.0383908, -0.00838349, -0.0181314, -0.00353384, -0.0182579, -0, 0, -0.061653, -0.0186044, -0.00832757, -0.0134227, -0.00379325, -0.0187587, -0, 0, -0.0580528, -0.0173559, -0.00826604, -0.0136066, -0.0109505, -0.0239675], dtype=np.float32).reshape(4, 4, 2) warped_live_field = np.array( [1, 1, 0.519703, 0.443642, 1, 0.482966, 0.350619, 0.329146, 1, 0.381416, 0.249635, 0.227962, 1, 0.261739, 0.166676, 0.117205], np.float32).reshape(4, 4) canonical_field = np.array( [-1, 1, 0.375, 0.25, -1, 0.324999, 0.199999, 0.149999, 1, 0.175001, 0.100001, 0.0500006, 1, 0.0750004, 4.41074e-07, -0.0999996], np.float32).reshape(4, 4) # @formatter:on smoothing_gradient_out = st.compute_smoothing_term_gradient_vectorized(warp_field) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, smoothing_gradient_out) energy_out = st.compute_smoothing_term_energy(warp_field, warped_live_field, canonical_field) expected_gradient_out = np.array([[[[[0., 0.], [0., 0.], [-0.08174722, -0.0152381], [0.01477674, -0.0024711]], [[0., 0.], [-0.08161432, -0.11682741], [0.05004385, 0.0150394], [0.01285562, 0.0012277]], [[0., 0.], [-0.14231893, -0.0052482], [0.0487855, 0.0154103], [0.01143216, -0.000628]], [[0., 0.], [-0.10423936, -0.0198567], [0.05253275, 0.0139263], [-0.00984171, -0.0155697]]]]], dtype=np.float32) self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) self.assertAlmostEqual(0.002550773788243532, energy_out) smoothing_gradient_out, energy_out = \ st.compute_smoothing_term_gradient_direct(warp_field, warped_live_field, canonical_field) self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) # See note at top of file on why expected energies are different for the vectorized/non-vectorized version self.assertAlmostEqual(0.001989291487916489, energy_out)
def test_smoothing_term02(self): warped_live_field = np.array([[1., 1., 0.49999955], [1., 0.44999936, 0.34999937], [1., 0.35000065, 0.25000066]], dtype=np.float32) canonical_field = np.array([[1.0000000e+00, 1.0000000e+00, 3.7499955e-01], [1.0000000e+00, 3.2499936e-01, 1.9999936e-01], [1.0000000e+00, 1.7500064e-01, 1.0000064e-01]], dtype=np.float32) warp_field = np.array([[[0., 0.], [0., 0.], [-0.3, -0.2]], [[0., 0.], [-0.40, -0.40], [-0.1, -0.2]], [[0., 0.], [-0.6, -0.2], [-0.1, -0.1]]], dtype=np.float32) expected_gradient_out = np.array([[[0., 0.], [0., 0.], [-0.5, -0.2]], [[0., 0.], [-0.9, -1.2], [0.5, 0.1]], [[0., 0.], [-1.3, -0.1], [0.5, 0.2]]], dtype=np.float32) expected_energy_out = 0.14625 smoothing_gradient_out, smoothing_energy_out = \ st.compute_smoothing_term_gradient_direct(warp_field, warped_live_field, canonical_field) self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) self.assertAlmostEqual(smoothing_energy_out, expected_energy_out, places=6) smoothing_gradient_out = st.compute_smoothing_term_gradient_vectorized(warp_field) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, smoothing_gradient_out) smoothing_energy_out = st.compute_smoothing_term_energy(warp_field, warped_live_field, canonical_field) # See note at top of file on why expected energies are different for the vectorized/non-vectorized version expected_energy_out = 0.39 self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) self.assertAlmostEqual(smoothing_energy_out, expected_energy_out, places=6)
def compute_smoothing_term_energy(warp_field, warped_live_field=None, canonical_field=None, band_union_only=True): if band_union_only and (warped_live_field is None or canonical_field is None): raise ValueError( "To determine the narrow band union, warped_live_field and canonical_field should be defined." " Otherwise, please set the 'band_union_only argument' to 'False'") warp_gradient_u_x, warp_gradient_u_y = np.gradient(warp_field[:, :, 0]) warp_gradient_v_x, warp_gradient_v_y = np.gradient(warp_field[:, :, 1]) gradient_aggregate = \ warp_gradient_u_x ** 2 + warp_gradient_v_x ** 2 + warp_gradient_u_y ** 2 + warp_gradient_v_y ** 2 if band_union_only: set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, gradient_aggregate) smoothing_energy = 0.5 * np.sum(gradient_aggregate) return smoothing_energy
def __optimization_iteration_vectorized(self, warped_live_field, canonical_field, warp_field, band_union_only=True): live_gradient_y, live_gradient_x = np.gradient(warped_live_field) data_gradient_field = dt.compute_data_term_gradient_vectorized( warped_live_field, canonical_field, live_gradient_x, live_gradient_y) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, data_gradient_field) self.total_data_energy = \ dt.compute_data_term_energy_contribution(warped_live_field, canonical_field) * self.data_term_weight smoothing_gradient_field = st.compute_smoothing_term_gradient_vectorized( warp_field) self.total_smoothing_energy = \ st.compute_smoothing_term_energy(warp_field, warped_live_field, canonical_field) * self.smoothing_term_weight if self.visualizer.data_component_field is not None: np.copyto(self.visualizer.data_component_field, data_gradient_field) if self.visualizer.smoothing_component_field is not None: np.copyto(self.visualizer.smoothing_component_field, smoothing_gradient_field) if self.visualizer.level_set_component_field is not None: frame_info = getframeinfo(currentframe()) print( "Warning: level set term not implemented in vectorized version, " "passed level_set_component_field is not None, {:s} : {:d}". format(frame_info.filename, frame_info.lineno)) self.gradient_field = self.data_term_weight * data_gradient_field + \ self.smoothing_term_weight * smoothing_gradient_field if band_union_only: set_zeros_for_values_outside_narrow_band_union( warped_live_field, canonical_field, self.gradient_field) # *** Print information at focus voxel focus_x, focus_y = get_focus_coordinates() focus = (focus_y, focus_x) print("Point: ", focus_x, ",", focus_y, sep='', end='') dt.compute_local_data_term(warped_live_field, canonical_field, focus_x, focus_y, live_gradient_x, live_gradient_y, method=dt.DataTermMethod.BASIC) focus_data_gradient = data_gradient_field[focus] print(" Data grad: ", BOLD_GREEN, -focus_data_gradient, RESET, sep='', end='') st.compute_local_smoothing_term_gradient( warp_field, focus_x, focus_y, method=self.smoothing_term_method, copy_if_zero=False, isomorphic_enforcement_factor=self.isomorphic_enforcement_factor) focus_smoothing_gradient = smoothing_gradient_field[ focus] * self.smoothing_term_weight print(" Smoothing grad (scaled): ", BOLD_GREEN, -focus_smoothing_gradient, RESET, sep='', end='') # *** if self.sobolev_smoothing_enabled: convolve_with_kernel_preserve_zeros(self.gradient_field, self.sobolev_kernel, True) np.copyto(warp_field, -self.gradient_field * self.gradient_descent_rate) warp_lengths = np.linalg.norm(warp_field, axis=2) maximum_warp_length_at = np.unravel_index(np.argmax(warp_lengths), warp_lengths.shape) maximum_warp_length = warp_lengths[maximum_warp_length_at] # *** print(" Warp: ", BOLD_GREEN, warp_field[focus], RESET, " Warp length: ", BOLD_GREEN, np.linalg.norm(warp_field[focus]), RESET, sep='') # *** get_and_print_interpolation_data(canonical_field, warped_live_field, warp_field, focus_x, focus_y) u_vectors = warp_field[:, :, 0].copy() v_vectors = warp_field[:, :, 1].copy() out_warped_live_field, (out_u_vectors, out_v_vectors) = \ cpp_extension.resample(warped_live_field, canonical_field, u_vectors, v_vectors) np.copyto(warped_live_field, out_warped_live_field) # some entries might have been erased due to things in the live sdf becoming truncated warp_field[:, :, 0] = out_u_vectors warp_field[:, :, 1] = out_v_vectors return maximum_warp_length, Point2d(maximum_warp_length_at[1], maximum_warp_length_at[0])
def test_data_term04(self): # corresponds to test_data_term_gradient01 in C++ warped_live_field = np.array( [[1., 1., 0.49404836, 0.4321034], [1., 0.44113636, 0.34710377, 0.32715625], [1., 0.3388706, 0.24753733, 0.22598255], [1., 0.21407352, 0.16514614, 0.11396749]], dtype=np.float32) canonical_field = np.array( [[-1.0000000e+00, 1.0000000e+00, 3.7499955e-01, 2.4999955e-01], [-1.0000000e+00, 3.2499936e-01, 1.9999936e-01, 1.4999935e-01], [1.0000000e+00, 1.7500064e-01, 1.0000064e-01, 5.0000645e-02], [1.0000000e+00, 7.5000443e-02, 4.4107438e-07, -9.9999562e-02]], dtype=np.float32) expected_gradient_out = np.array( [[[0., 0.], [-0., -0.], [-0.33803707, -0.17493579], [-0.11280416, -0.1911128]], [[-11.177273, 0.], [-0.37912706, -0.38390794], [-0.08383488, -0.1813143], [-0.03533841, -0.18257865]], [[-0., 0.], [-0.6165301, -0.18604389], [-0.08327565, -0.13422713], [-0.03793251, -0.18758681]], [[-0., 0.], [-0.5805285, -0.17355914], [-0.0826604, -0.13606551], [-0.10950545, -0.23967531]]], dtype=np.float32) expected_gradient_out_band_union_only = np.array( [[[0., 0.], [-0., -0.], [-0.33803707, -0.17493579], [-0.11280416, -0.1911128]], [[-0., 0.], [-0.37912706, -0.38390794], [-0.08383488, -0.1813143], [-0.03533841, -0.18257865]], [[-0., 0.], [-0.6165301, -0.18604389], [-0.08327565, -0.13422713], [-0.03793251, -0.18758681]], [[-0., 0.], [-0.5805285, -0.17355914], [-0.0826604, -0.13606551], [-0.10950545, -0.23967531]]], dtype=np.float32) expected_energy_out = 4.142916451210006 expected_energy_out_band_union_only = 0.14291645121000718 live_gradient_y, live_gradient_x = np.gradient(warped_live_field) data_gradient_out, energy_out = \ dt.compute_data_term_gradient_direct(warped_live_field, canonical_field, live_gradient_x, live_gradient_y, band_union_only=False) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out) data_gradient_out, energy_out = \ dt.compute_data_term_gradient_direct(warped_live_field, canonical_field, live_gradient_x, live_gradient_y, band_union_only=True) self.assertTrue( np.allclose(data_gradient_out, expected_gradient_out_band_union_only)) self.assertAlmostEqual(energy_out, expected_energy_out_band_union_only) data_gradient_out = \ dt.compute_data_term_gradient_vectorized(warped_live_field, canonical_field, live_gradient_x, live_gradient_y) self.assertTrue(np.allclose(data_gradient_out, expected_gradient_out)) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, data_gradient_out) self.assertTrue( np.allclose(data_gradient_out, expected_gradient_out_band_union_only)) energy_out = dt.compute_data_term_energy_contribution( warped_live_field, canonical_field, band_union_only=False) self.assertAlmostEqual(energy_out, expected_energy_out, places=6) energy_out = dt.compute_data_term_energy_contribution( warped_live_field, canonical_field) self.assertAlmostEqual(energy_out, expected_energy_out_band_union_only)
def test_smoothing_term03(self): warped_live_field = np.array([[1., 1., 0.49999955, 0.42499956], [1., 0.44999936, 0.34999937, 0.32499936], [1., 0.35000065, 0.25000066, 0.22500065], [1., 0.20000044, 0.15000044, 0.07500044]], dtype=np.float32) canonical_field = np.array([[1.0000000e+00, 1.0000000e+00, 3.7499955e-01, 2.4999955e-01], [1.0000000e+00, 3.2499936e-01, 1.9999936e-01, 1.4999935e-01], [1.0000000e+00, 1.7500064e-01, 1.0000064e-01, 5.0000645e-02], [1.0000000e+00, 7.5000443e-02, 4.4107438e-07, -9.9999562e-02]], dtype=np.float32) warp_field = np.array([[[0., 0.], [0., 0.], [-0.35937524, -0.18750024], [-0.13125, -0.17500037], ], [[0., 0.], [-0.4062504, -0.4062496], [-0.09375, -0.1874992], [-0.04375001, -0.17499907], ], [[0., 0.], [-0.65624946, -0.21874908], [-0.09375, -0.1499992], [-0.04375001, -0.21874908], ], [[0., 0.], [-0.5312497, -0.18750025], [-0.09374999, -0.15000032], [-0.13125001, -0.2625004], ]], dtype=np.float32) expected_gradient_out = np.array([[[0., 0.], [0., 0.], [-0.8531257, -0.20000115], [0.14062527, 0.01249856]], [[0., 0.], [-0.8750021, -1.2187502], [0.52812564, 0.16875133], [0.13749997, 0.05625144]], [[0., 0.], [-1.5937477, -0.13124725], [0.51249945, 0.17500085], [0.13749999, -0.06874855]], [[0., 0.], [-0.8437496, -0.19375136], [0.47499973, 0.14999892], [-0.125, -0.1562514]]], dtype=np.float32) expected_energy_out = 0.2126010925276205 smoothing_gradient_out, energy_out = \ st.compute_smoothing_term_gradient_direct(warp_field, warped_live_field, canonical_field) self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out, places=6) smoothing_gradient_out = st.compute_smoothing_term_gradient_vectorized(warp_field) set_zeros_for_values_outside_narrow_band_union(warped_live_field, canonical_field, smoothing_gradient_out) energy_out = st.compute_smoothing_term_energy(warp_field, warped_live_field, canonical_field) # See note at top of file on why expected energies are different for the vectorized/non-vectorized version expected_energy_out = 0.2802989184856415 self.assertTrue(np.allclose(smoothing_gradient_out, expected_gradient_out)) self.assertAlmostEqual(energy_out, expected_energy_out, places=6)