Beispiel #1
0
def test_apply_transformations() -> None:
    """
    Testing the function applying a series of transformations to a given image
    """
    operations = [
        ImageTransformationBase.identity(),
        ImageTransformationBase.translateX(0.3),
        ImageTransformationBase.horizontal_flip()
    ]

    # Case 1 on segmentations
    image_as_tensor = torch.tensor(
        [[[2, 1, 0], [1, 2, 0], [0, 0, 2]], [[2, 1, 0], [1, 2, 0], [0, 0, 2]]],
        dtype=torch.int32)
    transformed_tensor = ImageTransformationBase.apply_transform_on_3d_image(
        image=image_as_tensor, transforms=operations)
    expected = torch.tensor([[[1, 2, 0], [2, 1, 0], [0, 0, 0]],
                             [[1, 2, 0], [2, 1, 0], [0, 0, 0]]])
    assert torch.all(expected == transformed_tensor)

    # Case 2 on image
    image_as_tensor = torch.tensor(
        [[[1, 0.5, 0.1], [0.5, 1, 0.1], [0.1, 0.1, 1]],
         [[1, 0.5, 0.1], [0.5, 1, 0.1], [0.1, 0.1, 1]]],
        dtype=torch.float32)
    transformed_tensor = ImageTransformationBase.apply_transform_on_3d_image(
        image=image_as_tensor, transforms=operations)
    expected = torch.tensor([[[0.5, 1, 0], [1, 0.5, 0], [0.1, 0.1, 0]],
                             [[0.5, 1, 0], [1, 0.5, 0], [0.1, 0.1, 0]]])
    np.testing.assert_allclose(transformed_tensor, expected, rtol=0.02)
Beispiel #2
0
def test_RandomSliceTransformation_pipeline() -> None:
    """
    Test the RandomSerial transformation pipeline for online data augmentation.
    """
    # Set random seeds for transformations
    np.random.seed(1)
    random.seed(0)

    one_channel_image = torch.tensor(
        [[[2, 1, 0], [1, 2, 0], [0, 0, 2]], [[2, 1, 0], [1, 2, 0], [0, 0, 2]]],
        dtype=torch.int32)
    image_with_two_channels = torch.stack(
        (one_channel_image, one_channel_image), dim=0)

    # Case no transformation applied
    pipeline = augmentation.RandomSliceTransformation(
        probability_transformation=0,
        is_transformation_for_segmentation_maps=True)
    transformed = pipeline(image_with_two_channels)
    assert torch.all(image_with_two_channels == transformed)

    # Case separate transformation per channel
    pipeline = augmentation.RandomSliceTransformation(
        probability_transformation=1,
        is_transformation_for_segmentation_maps=True,
        use_joint_channel_transformation=False)
    transformed = pipeline(image_with_two_channels)
    expected_transformations_channel_1 = [
        ImageTransformationBase.rotate(-7),
        ImageTransformationBase.translateX(0.011836899667533166),
        ImageTransformationBase.translateY(-0.04989873172751189),
        ImageTransformationBase.horizontal_flip()
    ]
    expected_transformations_channel_2 = [
        ImageTransformationBase.rotate(-1),
        ImageTransformationBase.translateX(-0.04012366553408523),
        ImageTransformationBase.translateY(-0.08525151327425498),
        ImageTransformationBase.horizontal_flip()
    ]
    expected = _compute_expected_pipeline_result(
        transformations=[
            expected_transformations_channel_1,
            expected_transformations_channel_2
        ],
        input_image=image_with_two_channels)
    assert torch.all(transformed == expected)

    # Case same transformation for all channels
    pipeline = augmentation.RandomSliceTransformation(
        probability_transformation=1,
        is_transformation_for_segmentation_maps=True,
        use_joint_channel_transformation=True)
    transformed = pipeline(image_with_two_channels)
    expected_transformations_channel_1 = [
        ImageTransformationBase.rotate(9),
        ImageTransformationBase.translateX(-0.0006422133534675356),
        ImageTransformationBase.translateY(0.07352055509855618),
        ImageTransformationBase.horizontal_flip()
    ]
    expected = _compute_expected_pipeline_result(
        transformations=[
            expected_transformations_channel_1,
            expected_transformations_channel_1
        ],
        input_image=image_with_two_channels)
    assert torch.all(transformed == expected)

    # Case for images - convert to range 0-1 first
    image_with_two_channels = image_with_two_channels / 4.0
    pipeline = augmentation.RandomSliceTransformation(
        probability_transformation=1,
        is_transformation_for_segmentation_maps=False,
        use_joint_channel_transformation=True)
    transformed = pipeline(image_with_two_channels)
    expected_transformations_channel_1 = [
        ImageTransformationBase.rotate(8),
        ImageTransformationBase.translateX(-0.02782961037858135),
        ImageTransformationBase.translateY(0.06066901082924045),
        ImageTransformationBase.adjust_contrast(0.2849887878176489),
        ImageTransformationBase.adjust_brightness(1.0859799153800245)
    ]
    expected = _compute_expected_pipeline_result(
        transformations=[
            expected_transformations_channel_1,
            expected_transformations_channel_1
        ],
        input_image=image_with_two_channels)
    assert torch.all(transformed == expected)
Beispiel #3
0
def test_RandAugment_pipeline() -> None:
    """
    Test the RandAugment transformation pipeline for online data augmentation.
    """
    # Set random seeds for transformations
    np.random.seed(1)
    random.seed(0)

    # Get inputs
    one_channel_image = torch.tensor(
        [[[2, 1, 0], [1, 2, 0], [0, 0, 2]], [[2, 1, 0], [1, 2, 0], [0, 0, 2]]],
        dtype=torch.int32)
    two_channel_image = torch.stack((one_channel_image, one_channel_image),
                                    dim=0)

    # Case no transformation applied
    pipeline = augmentation.RandAugmentSlice(
        magnitude=3,
        n_transforms=0,
        is_transformation_for_segmentation_maps=True)
    transformed = pipeline(two_channel_image)
    assert torch.all(two_channel_image == transformed)

    # Case separate transformation per channel
    pipeline = augmentation.RandAugmentSlice(
        magnitude=3,
        n_transforms=1,
        is_transformation_for_segmentation_maps=True,
        use_joint_channel_transformation=False)
    expected_sampled_ops_channel_1 = [
        ImageTransformationBase.translateY(-0.3 * 0.2)
    ]
    expected_sampled_ops_channel_2 = [
        ImageTransformationBase.horizontal_flip()
    ]
    expected = _compute_expected_pipeline_result(transformations=[
        expected_sampled_ops_channel_1, expected_sampled_ops_channel_2
    ],
                                                 input_image=two_channel_image)
    transformed = pipeline(two_channel_image)
    assert torch.all(transformed == expected)

    # Case same transformation for all channels
    pipeline = augmentation.RandAugmentSlice(
        magnitude=5,
        n_transforms=2,
        is_transformation_for_segmentation_maps=True,
        use_joint_channel_transformation=True)
    transformed = pipeline(two_channel_image)

    expected_sampled_ops_channel = [
        ImageTransformationBase.rotate(0.5 * 30),
        ImageTransformationBase.translateY(0.5 * 0.2)
    ]

    expected = _compute_expected_pipeline_result(transformations=[
        expected_sampled_ops_channel, expected_sampled_ops_channel
    ],
                                                 input_image=two_channel_image)
    assert torch.all(transformed == expected)

    # Case for images
    two_channel_image = two_channel_image / 2.0
    pipeline = augmentation.RandAugmentSlice(
        magnitude=3,
        n_transforms=1,
        use_joint_channel_transformation=True,
        is_transformation_for_segmentation_maps=False)
    transformed = pipeline(two_channel_image)
    expected_sampled_ops_channel = [
        ImageTransformationBase.adjust_contrast(1 - 0.3)
    ]
    expected = _compute_expected_pipeline_result(transformations=[
        expected_sampled_ops_channel, expected_sampled_ops_channel
    ],
                                                 input_image=two_channel_image)
    assert torch.all(transformed == expected)
Beispiel #4
0
                       atol=0.1)


def _check_transformation_result(image_as_tensor: torch.Tensor,
                                 transformation: Callable,
                                 expected: torch.Tensor) -> None:
    test_tensor_pil = TF.to_pil_image(image_as_tensor)
    transformed = TF.to_tensor(transformation(test_tensor_pil)).squeeze()
    np.testing.assert_allclose(transformed, expected, rtol=0.02)


# Augmentation pipeline tests


@pytest.mark.parametrize(["transformation", "expected"],
                         [(ImageTransformationBase.horizontal_flip(),
                           torch.tensor([[0, 1, 2], [0, 2, 1], [2, 0, 0]])),
                          (ImageTransformationBase.rotate(45),
                           torch.tensor([[1, 0, 0], [2, 2, 2], [1, 0, 0]])),
                          (ImageTransformationBase.translateX(0.3),
                           torch.tensor([[0, 2, 1], [0, 1, 2], [0, 0, 0]])),
                          (ImageTransformationBase.translateY(0.3),
                           torch.tensor([[0, 0, 0], [2, 1, 0], [1, 2, 0]])),
                          (ImageTransformationBase.identity(),
                           torch.tensor([[2, 1, 0], [1, 2, 0], [0, 0, 2]]))])
def test_transformations_for_segmentations(transformation: Callable,
                                           expected: torch.Tensor) -> None:
    """
    Tests each individual transformation of the ImageTransformationBase class on a 2D input representing
    a segmentation map.
    """