コード例 #1
0
ファイル: dropped.py プロジェクト: jgornet/NeuroTorch
    def augment(self, bounding_box):
        # Get dropped slices and location
        dropped_slices = 2 * random.randrange(1, self.max_slices // 2)
        location = random.randrange(dropped_slices,
                                    bounding_box.getSize()[1] - dropped_slices)

        # Get enlarged bounding box
        edge1, edge2 = bounding_box.getEdges()
        edge2 = edge2 + Vector(0, dropped_slices, 0)
        initial_bounding_box = BoundingBox(edge1, edge2)

        # Get data
        raw, label = self.getParent().get(initial_bounding_box)

        # Augment Numpy arrays
        augmented_raw, augmented_label = self.drop(
            raw, label, dropped_slices=dropped_slices, location=location)

        # Convert back into the data format
        augmented_raw_data = Data(augmented_raw, bounding_box)
        augmented_label_data = Data(augmented_label, bounding_box)

        return (augmented_raw_data, augmented_label_data)
コード例 #2
0
    def augment(self, bounding_box):
        # Get error and location
        error = random.randrange(2, self.max_error)
        x_len = bounding_box.getSize()[0]
        location = random.randrange(10, x_len - 10)

        # Get initial bounding box
        edge1, edge2 = bounding_box.getEdges()
        edge2 += Vector(20, error, 0)
        initial_bounding_box = BoundingBox(edge1, edge2)

        # Get data
        raw_data, label_data = self.getParent().get(initial_bounding_box)
        raw, label = (raw_data.getArray().copy(), label_data.getArray().copy())
        augmented_raw, augmented_label = self.stitch(raw,
                                                     label,
                                                     location=location,
                                                     error=error)

        # Convert to the data format
        augmented_raw_data = Data(augmented_raw, bounding_box)
        augmented_label_data = Data(augmented_label, bounding_box)

        return (augmented_raw_data, augmented_label_data)
コード例 #3
0
 def setIterationSize(self, iteration_size):
     self.iteration_size = BoundingBox(Vector(0, 0, 0),
                                       iteration_size.getSize())
コード例 #4
0
class Array:
    """
    A dataset containing a 3D volumetric array
    """
    def __init__(self,
                 array: np.ndarray,
                 bounding_box: BoundingBox = None,
                 iteration_size: BoundingBox = BoundingBox(
                     Vector(0, 0, 0), Vector(128, 128, 32)),
                 stride: Vector = Vector(64, 64, 16)):
        """
        Initializes a volume with a bounding box and iteration parameters

        :param array: A 3D Numpy array
        :param bounding_box: The bounding box encompassing the volume
        :param iteration_size: The bounding box of each data sample in the
dataset iterable
        :param stride: The stride displacement of each data sample in the
dataset iterable. The displacement proceeds first from X then to Y then to Z.
        """
        if isinstance(array, np.ndarray):
            self._setArray(array)
        elif isinstance(array, BoundingBox):
            self.createArray(array)
        else:
            raise ValueError("array must be an ndarray or a BoundingBox")

        self.setBoundingBox(bounding_box)
        self.setIteration(iteration_size=iteration_size, stride=stride)
        super().__init__()

    def get(self, bounding_box: BoundingBox) -> Data:
        """
        Requests a data sample from the volume. If the bounding box does
not exist, then the method raises a ValueError.

        :param bounding_box: The bounding box of the request data sample
        :return: The data sample requested
        """
        if bounding_box.isDisjoint(self.getBoundingBox()):
            error_string = ("Bounding box must be inside dataset " +
                            "dimensions instead bounding box is {} while " +
                            "the dataset dimensions are {}")
            error_string = error_string.format(bounding_box,
                                               self.getBoundingBox())
            raise ValueError(error_string)

        sub_bounding_box = bounding_box.intersect(self.getBoundingBox())
        array = self.getArray(sub_bounding_box)

        before_pad = bounding_box.getEdges()[0] - sub_bounding_box.getEdges(
        )[0]
        after_pad = bounding_box.getEdges()[1] - sub_bounding_box.getEdges()[1]

        if before_pad != Vector(0, 0, 0) or after_pad != Vector(0, 0, 0):
            pad_size = tuple(
                zip(before_pad.getNumpyDim(), after_pad.getNumpyDim()))
            array = np.pad(array, pad_width=pad_size, mode="constant")

        return Data(array, bounding_box)

    def set(self, data: Data):
        """
        Sets a section of the volume within the provided bounding box with the
given data.

        :param data: The data packet to set the volume
        """
        data_bounding_box = data.getBoundingBox()
        data_array = data.getArray()

        if not data_bounding_box.isSubset(self.getBoundingBox()):
            raise ValueError("The bounding box must be a subset of the "
                             " volume")

        data_edge1, data_edge2 = data_bounding_box.getEdges()
        array_edge1, array_edge2 = self.getBoundingBox().getEdges()

        edge1 = data_edge1 - array_edge1
        edge2 = data_edge2 - array_edge1

        x1, y1, z1 = edge1.getComponents()
        x2, y2, z2 = edge2.getComponents()

        self.array[z1:z2, y1:y2, x1:x2] = data_array

    def blend(self, data: Data):
        """
        Blends a section of the volume within the provided bounding box with
the given data by taking the elementwise maximum value.

        :param data: The data packet to blend into the volume
        """
        array = self.get(data.getBoundingBox()).getArray()
        array = np.maximum(array, data.getArray())

        result = Data(array, data.getBoundingBox())

        self.set(result)

    def getArray(self, bounding_box: BoundingBox = None) -> np.ndarray:
        """
        Retrieves the array contents of the volume. If a bounding box is
provided, the subsection is returned.

        :param bounding_box: The bounding box of a subsection of the volume.
If the bounding box is outside of the volume, a ValueError is raised.
        """
        if bounding_box is None:
            return self.array

        else:
            if not bounding_box.isSubset(self.getBoundingBox()):
                raise ValueError("The bounding box must be a subset" +
                                 " of the volume")

            centered_bounding_box = bounding_box - self.getBoundingBox(
            ).getEdges()[0]
            edge1, edge2 = centered_bounding_box.getEdges()
            x1, y1, z1 = edge1.getComponents()
            x2, y2, z2 = edge2.getComponents()

            return self.array[z1:z2, y1:y2, x1:x2]

    def _setArray(self, array):
        self.array = array

    def getBoundingBox(self) -> BoundingBox:
        """
        Retrieves the bounding box of the volume

        :return: The bounding box of the volume
        """
        return self.bounding_box

    def setBoundingBox(self,
                       bounding_box: BoundingBox = None,
                       displacement: Vector = None):
        """
        Sets the bounding box of the volume. By default, it sets the bounding
box to the volume size

        :param bounding_box: The bounding box of the volume
        :param displacement: The displacement of the bounding box from the
origin
        """
        if bounding_box is None:
            self.bounding_box = BoundingBox(
                Vector(0, 0, 0), Vector(*self.getArray().shape[::-1]))
        else:
            self.bounding_box = bounding_box

        if displacement is not None:
            self.bounding_box = self.bounding_box + displacement

    def setIteration(self, iteration_size: BoundingBox, stride: Vector):
        """
        Sets the parameters for iterating through the dataset

        :param iteration_size: The size of each data sample in the volume
        :param stride: The displacement of each iteration
        """
        if not isinstance(iteration_size, BoundingBox):
            error_string = ("iteration_size must have type BoundingBox" +
                            " instead it has type {}")
            error_string = error_string.format(type(iteration_size))
            raise ValueError(error_string)

        if not isinstance(stride, Vector):
            raise ValueError("stride must have type Vector")

        if not iteration_size.isSubset(
                BoundingBox(Vector(0, 0, 0),
                            self.getBoundingBox().getSize())):
            raise ValueError("iteration_size must be smaller than volume size")

        self.setIterationSize(iteration_size)
        self.setStride(stride)

        def ceil(x):
            return int(round(x))

        self.element_vec = Vector(
            *map(lambda L, l, s: ceil((L - l) / s + 1),
                 self.getBoundingBox().getSize().getComponents(),
                 self.iteration_size.getSize().getComponents(),
                 self.stride.getComponents()))

        self.index = 0

    def setIterationSize(self, iteration_size):
        self.iteration_size = BoundingBox(Vector(0, 0, 0),
                                          iteration_size.getSize())

    def setStride(self, stride):
        self.stride = stride

    def getIterationSize(self):
        return self.iteration_size

    def getStride(self):
        return self.stride

    def __len__(self):
        return self.element_vec[0] * self.element_vec[1] * self.element_vec[2]

    def __getitem__(self, idx):
        bounding_box = self._indexToBoundingBox(idx)
        result = self.get(bounding_box)

        return result

    def _indexToBoundingBox(self, idx):
        if idx >= len(self):
            self.index = 0
            raise StopIteration

        element_vec = np.unravel_index(idx,
                                       dims=self.element_vec.getComponents())

        element_vec = Vector(*element_vec)
        bounding_box = self.iteration_size + self.stride * element_vec

        return bounding_box

    def __enter__(self):
        pass

    def __exit__(self):
        pass