Example #1
0
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
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
    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
Example #7
0
    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])
Example #8
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)
Example #9
0
    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)