예제 #1
0
    def test_two_components(self):
        components = np.zeros((10, 10, 20), dtype=np.uint8)
        components[4:6, 4:6, 4:6] = 1
        components[4:6, 4:6, 14:16] = 2
        sprawl_area = np.zeros(components.shape, dtype=np.uint8)
        sprawl_area[2:8, 2:8, 2:18] = True
        sprawl_area[components > 0] = False
        fdt = np.zeros(components.shape, dtype=np.float64)
        mso = PyMSO()
        neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
        mso.set_neighbourhood(neigh, dist)
        mso.set_components(components)
        res = mso.optimum_erosion_calculate(fdt, components, sprawl_area)
        assert np.all(res == components)

        fdt[:] = 2
        fdt[:, :, 10] = 1
        components2 = np.zeros(components.shape, dtype=np.uint8)
        components2[2:8, 2:8, 2:10] = 1
        components2[2:8, 2:8, 11:18] = 2
        res = mso.optimum_erosion_calculate(fdt, components, sprawl_area)
        assert np.all(res == components2)
        fdt[5, 5, 10] = 2
        res = mso.optimum_erosion_calculate(fdt, components, sprawl_area)
        assert np.all(res == components)
예제 #2
0
 def test_fdt(self):
     mso = PyMSO()
     neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
     components = np.zeros((10, 10, 10), dtype=np.uint8)
     components[3:7, 3:7, 3:7] = 1
     mso.set_neighbourhood(neigh, dist)
     with pytest.raises(RuntimeError):
         mso.calculate_FDT()
     mso.set_components(components)
     with pytest.raises(RuntimeError):
         mso.calculate_FDT()
예제 #3
0
 def test_fdt_simple(self):
     mso = PyMSO()
     neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
     components = np.zeros((3, 3, 3), dtype=np.uint8)
     components[1, 1, 1] = 1
     mso.set_neighbourhood(neigh, dist)
     mso.set_components(components)
     mso.set_mu_array(np.ones(components.shape))
     arr = np.zeros(components.shape)
     arr[(0, 0, 0, 0, 2, 2, 2, 2), (0, 0, 2, 2, 0, 0, 2, 2),
         (0, 2, 0, 2, 0, 2, 0, 2)] = np.sqrt(3)
     arr[(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2),
         (0, 1, 1, 2, 0, 0, 2, 2, 0, 1, 1, 2),
         (1, 0, 2, 1, 0, 2, 0, 2, 1, 0, 2, 1), ] = np.sqrt(2)
     arr[(0, 1, 1, 1, 1, 2), (1, 0, 1, 1, 2, 1), (1, 1, 0, 2, 1, 1)] = 1
     res = mso.calculate_FDT()
     assert np.all(res == arr)
예제 #4
0
 def test_fdt_base(self):
     mso = PyMSO()
     neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
     components = np.zeros((10, 10, 10), dtype=np.uint8)
     components[3:7, 3:7, 3:7] = 1
     mso.set_neighbourhood(neigh, dist)
     mso.set_components(components)
     mso.set_mu_array(np.ones(components.shape))
     res = mso.calculate_FDT()
     arr = calculate_euclidean((components == 0).astype(np.uint8),
                               components, neigh, dist)
     assert np.all(res == arr)
     mso.set_mu_array(np.ones(components.shape) * 0.5)
     res = mso.calculate_FDT()
     assert np.all(res == arr * 0.5)
     mu = np.ones(components.shape) * 0.5
     mu[components > 0] = 1
     mso.set_mu_array(mu)
     arr *= 0.5
     arr[arr > 0] += 0.25
     arr[3:7, (0, 1, 2, 0, 1, 2, 9, 8, 7, 9, 8, 7),
         (0, 1, 2, 9, 8, 7, 0, 1, 2, 9, 8, 7)] += np.sqrt(2) / 4 - 0.25
     for i in range(3):
         lb = i
         ub = 9 - i
         arr[lb, lb + 1:ub, (lb, ub)] += np.sqrt(2) / 4 - 0.25
         arr[lb, (lb, ub), lb + 1:ub] += np.sqrt(2) / 4 - 0.25
         arr[ub, lb + 1:ub, (lb, ub)] += np.sqrt(2) / 4 - 0.25
         arr[ub, (lb, ub), lb + 1:ub] += np.sqrt(2) / 4 - 0.25
         for el in itertools.product([lb, ub], repeat=3):
             arr[el] += np.sqrt(3) / 4 - 0.25
     for z, (y, x) in itertools.product([2, 7],
                                        itertools.product([0, 9],
                                                          repeat=2)):
         arr[z, y, x] += np.sqrt(2) / 4 - 0.25
     for z, (y, x) in itertools.product([2, 7],
                                        itertools.product([1, 8],
                                                          repeat=2)):
         arr[z, y, x] += np.sqrt(2) / 4 - 0.25
     for z, (y, x) in itertools.product([1, 8],
                                        itertools.product([0, 9],
                                                          repeat=2)):
         arr[z, y, x] += np.sqrt(2) / 4 - 0.25
     res2 = mso.calculate_FDT()
     assert np.allclose(res2, arr)
예제 #5
0
    def test_bridges(self):
        components = np.zeros((10, 20, 30), dtype=np.uint8)
        components[4:6, 4:6, 4:6] = 1
        components[4:6, 4:6, 24:26] = 2
        components[4:6, 14:16, 14:16] = 3
        sprawl_area = np.zeros(components.shape, dtype=np.uint8)
        sprawl_area[2:9, 2:10, 2:28] = True
        sprawl_area[2:9, 10:18, 11:20] = True
        sprawl_area[components > 0] = False
        fdt = np.ones(components.shape, dtype=np.float64) * 2
        fdt[:, 10, :] = 1
        fdt[:, :, 10] = 1
        fdt[:, :, 20] = 1

        comp = np.copy(components)
        comp[2:9, 2:10, 2:10] = 1
        comp[2:9, 2:10, 21:28] = 2
        comp[2:9, 11:18, 11:20] = 3
        neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
        mso = PyMSO()
        mso.set_neighbourhood(neigh, dist)
        mso.set_components(components)
        res = mso.optimum_erosion_calculate(fdt, components, sprawl_area)
        assert np.all(res == comp)
        fdt2 = np.copy(fdt)
        fdt2[5, 5, 10] = 2
        comp2 = np.copy(comp)
        comp2[5, 5, 10] = 1
        comp2[2:9, 2:10, 11:20] = 1
        res = mso.optimum_erosion_calculate(fdt2, components, sprawl_area)
        assert np.all(res == comp2)
        fdt2 = np.copy(fdt)
        fdt2[5, 5, 20] = 2
        comp2 = np.copy(comp)
        comp2[5, 5, 20] = 2
        comp2[2:9, 2:10, 11:20] = 2
        res = mso.optimum_erosion_calculate(fdt2, components, sprawl_area)
        assert np.all(res == comp2)
        fdt2 = np.copy(fdt)
        fdt2[5, 10, 15] = 2
        comp2 = np.copy(comp)
        comp2[5, 10, 15] = 3
        comp2[2:9, 2:10, 11:20] = 3
        res = mso.optimum_erosion_calculate(fdt2, components, sprawl_area)
        assert np.all(res == comp2)
예제 #6
0
    def test_two_components(self):
        components = np.zeros((10, 10, 20), dtype=np.uint8)
        components[:] = 1
        components[2:8, 2:8, 2:18] = 0
        components[4:6, 4:6, 4:6] = 2
        components[4:6, 4:6, 14:16] = 3
        mu_arr = np.zeros(components.shape, dtype=np.float64)
        mu_arr[components == 0] = 0.5
        mu_arr[components > 1] = 1

        mso = PyMSO()
        neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
        mso.set_neighbourhood(neigh, dist)
        mso.set_components(components)
        mso.set_mu_array(mu_arr)
        mso.set_components_num(3)

        mso.run_MSO(10)
        mso.steps_done()
        # res = mso.get_result_catted()
        arr = np.copy(components)
        arr[arr == 1] = 0
        arr[3:7, 3:7, 3:10] = 2
        arr[3:7, 3:7, 10:17] = 3
        # assert np.all(arr == res)

        mu_arr[2:8, 2:8, 10] = 0.08
        mso.set_mu_array(mu_arr)
        mso.run_MSO(10)
        # res = mso.get_result_catted()
        arr[2:8, 2:8, 2:10] = 2
        arr[2:8, 2:8, 11:18] = 3
        arr[3:7, 3:7, 10] = 0
        # assert np.all(arr == res)
        mu_arr[2:8, 2:8, 9] = 0.08
        mso.set_mu_array(mu_arr)
        arr[2:8, 2:8, 2:9] = 2
        arr[2:8, 2:8, 9] = 0
        arr[2:8, 2:8, 11:18] = 3
        mso.run_MSO(10)
        res = mso.get_result_catted()
        assert np.all(arr == res)
예제 #7
0
    def sprawl(
        cls,
        sprawl_area: np.ndarray,
        core_objects: np.ndarray,
        data: np.ndarray,
        components_num: int,
        spacing,
        side_connection: bool,
        operator: Callable[[Any, Any], bool],
        arguments: dict,
        lower_bound,
        upper_bound,
    ):
        if components_num > 250:
            raise SegmentationLimitException("Current implementation of MSO do not support more than 250 components")
        mso = PyMSO()
        neigh, dist = calculate_distances_array(spacing, get_neigh(side_connection))
        components_arr = np.copy(core_objects).astype(np.uint8)
        components_arr[components_arr > 0] += 1
        components_arr[sprawl_area == 0] = 1
        mso.set_neighbourhood(neigh, dist)
        mso.set_components(components_arr, components_num + 1)
        mso.set_use_background(False)
        try:
            mu_array = calculate_mu(data.copy("C"), lower_bound, upper_bound, MuType.base_mu)
        except OverflowError:
            raise SegmentationLimitException("Wrong range for ")
        if arguments["reflective"]:
            mu_array[mu_array < 0.5] = 1 - mu_array[mu_array < 0.5]
        mso.set_mu_array(mu_array)
        try:
            mso.run_MSO(arguments["step_limits"])
        except RuntimeError as e:
            if e.args[0] == "to many steps: constrained dilation":
                raise SegmentationLimitException(*e.args)
            raise

        # print("Steps: ", mso.steps_done(), file=sys.stderr)
        result = mso.get_result_catted()
        result[result > 0] -= 1
        return result
예제 #8
0
    def _test_background_simple(self):
        components = np.ones((20, 20, 20), dtype=np.uint8)
        components[1:-1, 1:-1, 1:-1] = 0
        components[9:11, 9:11, 9:11] = 2

        mu_array = np.zeros(components.shape)
        mu_array[1:-1, 1:-1, 1:-1] = 0.7
        mu_array[3:-3, 3:-3, 3:-3] = 0.6
        mu_array[5:-5, 5:-5, 5:-5] = 0.4
        mu_array[6:-6, 6:-6, 6:-6] = 0.6
        mu_array[8:-8, 8:-8, 8:-8] = 0.7
        mu_array[components > 0] = 1.0
        mso = PyMSO()
        neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
        mso.set_neighbourhood(neigh, dist)
        mso.set_use_background(True)
        mso.set_components(components, 3)
        mso.set_mu_array(mu_array)
        mso.set_components_num(3)
        mso.run_MSO(10)
        mso.get_result_catted()
예제 #9
0
 def test_chain_component_base(self):
     for i in range(2, 10):
         components = np.zeros((4, 5, i * 5), dtype=np.uint8)
         for j in range(i):
             components[2, 2, 5 * j + 2] = j + 1
         fdt = np.ones(components.shape, dtype=np.float64) * 2
         for j in range(i - 1):
             fdt[:, :, j * 5 + 4] = 1
         sprawl_area = np.ones(components.shape, dtype=np.uint8)
         sprawl_area[components > 0] = False
         components2 = np.zeros(components.shape, dtype=np.uint8)
         for j in range(i):
             components2[:, :, (j * 5):(j * 5) + 4] = j + 1
         components2[:, :, -1] = i
         neigh, dist = calculate_distances_array((1, 1, 1),
                                                 NeighType.vertex)
         mso = PyMSO()
         mso.set_neighbourhood(neigh, dist)
         mso.set_components(components)
         res = mso.optimum_erosion_calculate(fdt, components, sprawl_area)
         assert np.all(res == components2)
예제 #10
0
 def test_chain_component(self):
     for i in range(2, 10):
         components = np.zeros((10, 10, i * 10), dtype=np.uint8)
         for j in range(i):
             components[4:6, 4:6, (10 * j + 4):(10 * j + 6)] = j + 1
         fdt = np.ones(components.shape, dtype=np.float64) * i * 10
         sprawl_area = np.zeros(components.shape, dtype=np.uint8)
         sprawl_area[2:8, 2:8, 2:(10 * i) - 2] = True
         sprawl_area[components > 0] = False
         components2 = np.zeros(components.shape, dtype=np.uint8)
         for j in range(i):
             components2[2:8, 2:8, (j * 10):(j + 1) * 10] = j + 1
         components2[:, :, :2] = 0
         components2[:, :, -2:] = 0
         mso = PyMSO()
         neigh, dist = calculate_distances_array((1, 1, 1),
                                                 NeighType.vertex)
         mso.set_neighbourhood(neigh, dist)
         mso.set_components(components)
         mso.set_mu_array(np.ones(components.shape))
         res = mso.constrained_dilation(fdt, components, sprawl_area)
         assert np.all(res == components2)
예제 #11
0
    def test_two_components_base(self):
        components = np.zeros((10, 10, 20), dtype=np.uint8)
        components[4:6, 4:6, 4:6] = 1
        components[4:6, 4:6, 14:16] = 2
        sprawl_area = np.zeros(components.shape, dtype=np.uint8)
        sprawl_area[2:8, 2:8, 2:18] = True
        sprawl_area[components > 0] = False
        fdt = np.zeros(components.shape, dtype=np.float64)
        mso = PyMSO()
        neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
        mso.set_neighbourhood(neigh, dist)
        mso.set_components(components)
        mso.set_mu_array(np.ones(components.shape))
        res = mso.constrained_dilation(fdt, components, sprawl_area)
        assert np.all(res == components)

        fdt[:] = 20
        # fdt[:, :, 10] = 1
        components2 = np.zeros(components.shape, dtype=np.uint8)
        components2[2:8, 2:8, 2:10] = 1
        components2[2:8, 2:8, 10:18] = 2
        res = mso.constrained_dilation(fdt, components, sprawl_area)
        assert np.all(res == components2)
예제 #12
0
 def test_high_fdt_two_components(self):
     components = np.zeros((10, 10, 20), dtype=np.uint8)
     components[4:6, 4:6, 4:6] = 1
     components[4:6, 4:6, 14:16] = 2
     sprawl_area = np.zeros(components.shape, dtype=np.uint8)
     sprawl_area[2:8, 2:8, 2:18] = True
     sprawl_area[components > 0] = False
     fdt = np.ones(components.shape, dtype=np.float64) * 20
     mso = PyMSO()
     neigh, dist = calculate_distances_array((1, 1, 1), NeighType.vertex)
     mso.set_neighbourhood(neigh, dist)
     mso.set_components(components)
     mso.set_mu_array(np.ones(components.shape))
     components2 = np.zeros(components.shape, dtype=np.uint8)
     components2[2:8, 2:8, 2:10] = 1
     components2[2:8, 2:8, 10:18] = 2
     fdt2 = np.copy(fdt)
     fdt2[:, :, 7] = 25
     components3 = np.copy(components2)
     components3[2:8, 2:8, 8:18] = 2
     components3[2:8, 2:8, 7] = 0
     res = mso.constrained_dilation(fdt2, components, sprawl_area)
     assert np.all(res == components3)
     fdt2 = np.copy(fdt)
     fdt2[:, :, 12] = 25
     components3 = np.copy(components2)
     components3[2:8, 2:8, 2:12] = 1
     components3[2:8, 2:8, 12] = 0
     res = mso.constrained_dilation(fdt2, components, sprawl_area)
     assert np.all(res == components3)
     fdt2 = np.copy(fdt)
     fdt2[:, :, 12] = 25
     fdt2[:, :, 7] = 25
     components3 = np.copy(components2)
     components3[2:8, 2:8, 7:13] = 0
     res = mso.constrained_dilation(fdt2, components, sprawl_area)
     assert np.all(res == components3)
예제 #13
0
class BaseMultiScaleOpening(TwoLevelThresholdBaseAlgorithm,
                            ABC):  # pragma: no cover
    @classmethod
    def get_fields(cls):
        return [
            AlgorithmProperty(
                "threshold",
                "Threshold",
                next(iter(double_threshold_dict.keys())),
                possible_values=double_threshold_dict,
                property_type=AlgorithmDescribeBase,
            ),
            AlgorithmProperty(
                "mu_mid",
                "Mu mid value",
                next(iter(mu_mid_dict.keys())),
                possible_values=mu_mid_dict,
                property_type=AlgorithmDescribeBase,
            ),
            AlgorithmProperty("step_limits",
                              "Limits of Steps",
                              100,
                              options_range=(1, 1000),
                              property_type=int),
        ] + super().get_fields()

    def get_info_text(self):
        return ("Threshold: " + ", ".join(map(str, self.threshold_info)) +
                "\nMid sizes: " + ", ".join(
                    map(str, self._sizes_array[1:self.components_num + 1])) +
                "\nFinal sizes: " + ", ".join(map(str, self.final_sizes[1:])) +
                f"\nsteps: {self.steps}")

    def __init__(self):
        super().__init__()
        self.finally_segment = None
        self.final_sizes = []
        self.threshold_info = [None, None]
        self.steps = 0
        self.mso = PyMSO()
        self.mso.set_use_background(True)

    def clean(self):
        self.sprawl_area = None
        self.mso = PyMSO()
        self.mso.set_use_background(True)
        super().clean()

    def set_image(self, image):
        super().set_image(image)
        self.threshold_info = [None, None]

    def calculation_run(self, report_fun) -> SegmentationResult:
        if self.new_parameters["side_connection"] != self.parameters[
                "side_connection"]:
            neigh, dist = calculate_distances_array(
                self.image.spacing,
                get_neigh(self.new_parameters["side_connection"]))
            self.mso.set_neighbourhood(neigh, dist)
        segment_data = super().calculation_run(report_fun)
        if segment_data is not None and self.components_num == 0:
            self.final_sizes = []
            return segment_data

        if segment_data is None:
            restarted = False
            finally_segment = np.copy(self.finally_segment)
        else:
            self.finally_segment = segment_data.roi
            finally_segment = segment_data.roi
            if np.max(finally_segment) > 250:
                raise SegmentationLimitException(
                    "Current implementation of MSO do not support more than 250 components"
                )
            components = finally_segment.astype(np.uint8)
            components[components > 0] += 1
            components[self.sprawl_area == 0] = 1
            self.mso.set_components(components, self.components_num)
            restarted = True

        if (restarted or self.old_threshold_info[1] != self.threshold_info[1]
                or self.new_parameters["mu_mid"] != self.parameters["mu_mid"]):
            if self.threshold_operator(self.threshold_info[1],
                                       self.threshold_info[0]):
                self.final_sizes = np.bincount(finally_segment.flat)
                return self.prepare_result(self.finally_segment)
            mu_calc: BaseMuMid = mu_mid_dict[self.new_parameters["mu_mid"]
                                             ["name"]]
            self.parameters["mu_mid"] = self.new_parameters["mu_mid"]
            sprawl_area = (self.sprawl_area > 0).astype(np.uint8)
            sprawl_area[finally_segment > 0] = 0
            mid_val = mu_calc.value(
                sprawl_area,
                self.channel,
                self.threshold_info[0],
                self.threshold_info[1],
                self.new_parameters["mu_mid"]["values"],
            )
            mu_array = calculate_mu_mid(self.channel, self.threshold_info[0],
                                        mid_val, self.threshold_info[1])
            self.mso.set_mu_array(mu_array)
            restarted = True

        if restarted or self.new_parameters["step_limits"] != self.parameters[
                "step_limits"]:
            self.parameters["step_limits"] = self.new_parameters["step_limits"]
            count_steps_factor = 20 if self.image.is_2d else 3
            self.mso.run_MSO(self.new_parameters["step_limits"],
                             count_steps_factor)
            self.steps = self.mso.steps_done()
            new_segment = self.mso.get_result_catted()
            new_segment[new_segment > 0] -= 1
            self.final_sizes = np.bincount(new_segment.flat)
            return self.prepare_result(new_segment)