Пример #1
0
    def _pad_sample(sample, size):
        padding = SegCollate._compute_padding(sample['image'].shape[1:3], size)

        if padding is not None:
            sample = sample.copy()
            sample['image'] = SegCollate._apply_padding_to_tensor(
                sample['image'], padding, value=0)
            if 'labels' in sample:
                sample['labels'] = SegCollate._apply_padding_to_tensor(
                    sample['labels'], padding, value=255)
            if 'mask' in sample:
                sample['mask'] = SegCollate._apply_padding_to_tensor(
                    sample['mask'], padding, value=255)
            if 'xf_pil' in sample:
                dy, dx = padding[1][0], padding[2][0]
                sample['xf_pil'] = affine.cat_nx2x3(
                    sample['xf_pil'][None, ...],
                    affine.translation_matrices(np.array([[dx, dy]])))[0]
            if 'xf_cv' in sample:
                dy, dx = padding[1][0], padding[2][0]
                sample['xf_cv'] = affine.cat_nx2x3(
                    affine.translation_matrices(np.array([[dx, dy]])),
                    sample['xf_cv'][None, ...])[0]

        return sample
Пример #2
0
    def pad_pair(self, sample0, sample1, min_size):
        sample0 = sample0.copy()
        sample1 = sample1.copy()
        image0 = sample0['image_arr']
        image1 = sample1['image_arr']
        img_size0 = image0.shape[:2]
        if img_size0[0] < min_size[0] or img_size0[1] < min_size[1]:
            # Padding required

            # Compute padding
            pad_h = max(min_size[0] - img_size0[0], 0)
            pad_w = max(min_size[1] - img_size0[1], 0)
            h0 = pad_h // 2
            h1 = pad_h - h0
            w0 = pad_w // 2
            w1 = pad_w - w0

            # Add an alpha channel to the image so that we can use it during standardisation
            # to ensure that the padding area has a value of 0, post mean-subtraction
            alpha_channel = np.ones(img_size0 +
                                    (1, ), dtype=image0.dtype) * 255
            image0 = np.append(image0[:, :, :3], alpha_channel, axis=2)
            image1 = np.append(image1[:, :, :3], alpha_channel, axis=2)

            # Apply
            sample0['image_arr'] = np.pad(image0, [[h0, h1], [w0, w1], [0, 0]],
                                          mode='constant',
                                          constant_values=0)
            sample1['image_arr'] = np.pad(image1, [[h0, h1], [w0, w1], [0, 0]],
                                          mode='constant',
                                          constant_values=0)
            if 'labels_arr' in sample0:
                sample0['labels_arr'] = np.pad(sample0['labels_arr'],
                                               [[h0, h1], [w0, w1]],
                                               mode='constant',
                                               constant_values=255)
                sample1['labels_arr'] = np.pad(sample1['labels_arr'],
                                               [[h0, h1], [w0, w1]],
                                               mode='constant',
                                               constant_values=255)
            if 'mask_arr' in sample0:
                sample0['mask_arr'] = np.pad(sample0['mask_arr'],
                                             [[h0, h1], [w0, w1]],
                                             mode='constant')
                sample1['mask_arr'] = np.pad(sample1['mask_arr'],
                                             [[h0, h1], [w0, w1]],
                                             mode='constant')
            if 'xf_cv' in sample0:
                pad_xlat = affine.translation_matrices(np.array([[w0, h0]]))
                sample0['xf_cv'] = affine.cat_nx2x3(
                    pad_xlat, sample0['xf_cv'][None, ...])[0]
                sample1['xf_cv'] = affine.cat_nx2x3(
                    pad_xlat, sample1['xf_cv'][None, ...])[0]
        return (sample0, sample1)
Пример #3
0
    def transform_pair(self, sample0, sample1):
        # Pad the image if necessary
        sample0, sample1 = self.pad_pair(sample0, sample1, self.crop_size)

        # Randomly choose positions of each crop
        extra = np.array(sample0['image_arr'].shape[:2]) - self.crop_size
        pos0 = np.round(extra *
                        self.rng.uniform(0.0, 1.0, size=(2, ))).astype(int)
        pos1 = pos0 + np.round(self.crop_offset * self.rng.uniform(
            -1.0, 1.0, size=(2, ))).astype(int)
        # Ensure pos1 cannot go out of bounds
        pos1 = np.clip(pos1, np.array([0, 0]), extra)

        # Extract crop and scale to target size
        sample0['image_arr'] = sample0['image_arr'][pos0[0]:pos0[0] +
                                                    self.crop_size[0],
                                                    pos0[1]:pos0[1] +
                                                    self.crop_size[1]]
        sample1['image_arr'] = sample1['image_arr'][pos1[0]:pos1[0] +
                                                    self.crop_size[0],
                                                    pos1[1]:pos1[1] +
                                                    self.crop_size[1]]

        sample0['mask_arr'] = sample0['mask_arr'][pos0[0]:pos0[0] +
                                                  self.crop_size[0],
                                                  pos0[1]:pos0[1] +
                                                  self.crop_size[1]]
        sample1['mask_arr'] = sample1['mask_arr'][pos1[0]:pos1[0] +
                                                  self.crop_size[0],
                                                  pos1[1]:pos1[1] +
                                                  self.crop_size[1]]

        if 'labels_arr' in sample0:
            sample0['labels_arr'] = sample0['labels_arr'][pos0[0]:pos0[0] +
                                                          self.crop_size[0],
                                                          pos0[1]:pos0[1] +
                                                          self.crop_size[1]]
            sample1['labels_arr'] = sample1['labels_arr'][pos1[0]:pos1[0] +
                                                          self.crop_size[0],
                                                          pos1[1]:pos1[1] +
                                                          self.crop_size[1]]

        if 'xf_cv' in sample0:
            sample0['xf_cv'] = affine.cat_nx2x3(
                affine.translation_matrices(-pos0[None, ::-1]),
                sample0['xf_cv'][None, ...])[0]
            sample1['xf_cv'] = affine.cat_nx2x3(
                affine.translation_matrices(-pos1[None, ::-1]),
                sample1['xf_cv'][None, ...])[0]
        return (sample0, sample1)
Пример #4
0
    def transform_single(self, sample):
        sample = sample.copy()

        # Flip flags
        flip_flags_xyd = self.rng.binomial(1, 0.5, size=(3, )) != 0
        flip_flags_xyd = flip_flags_xyd & np.array(
            [self.hflip, self.vflip, self.hvflip])

        sample['image_arr'] = self.flip_image(sample['image_arr'],
                                              flip_flags_xyd)

        if 'mask_arr' in sample:
            sample['mask_arr'] = self.flip_image(sample['mask_arr'],
                                                 flip_flags_xyd)

        if 'labels_arr' in sample:
            sample['labels_arr'] = self.flip_image(sample['labels_arr'],
                                                   flip_flags_xyd)

        if 'xf_cv' in sample:
            sample['xf_cv'] = affine.cat_nx2x3(
                affine.flip_xyd_matrices(flip_flags_xyd,
                                         sample['image_arr'].shape[:2]),
                sample['xf_cv'][None, ...],
            )[0]

        return sample
Пример #5
0
 def _compute_xf_0_to_1(pair):
     sample0 = pair['sample0']
     sample1 = pair['sample1']
     if 'xf_cv' in sample0 and 'xf_cv' in sample1:
         xf0_to_1_cv = affine.cat_nx2x3(
             sample1['xf_cv'][None, ...],
             affine.inv_nx2x3(sample0['xf_cv'][None, ...]))
         xf0_to_1 = affine.cv_to_torch(xf0_to_1_cv,
                                       sample1['image'].shape[1:3])
         pair['xf0_to_1_cv'] = xf0_to_1_cv[0]
         pair['xf0_to_1'] = xf0_to_1[0].astype(np.float32)
     elif 'xf_pil' in sample0 and 'xf_pil' in sample1:
         xf0_to_1_pil = affine.cat_nx2x3(
             affine.inv_nx2x3(sample0['xf_pil'][None, ...]),
             sample1['xf_pil'][None, ...])
         xf0_to_1 = affine.pil_to_torch(xf0_to_1_pil,
                                        sample1['image'].shape[1:3])
         pair['xf0_to_1_pil'] = xf0_to_1_pil[0]
         pair['xf0_to_1'] = xf0_to_1[0].astype(np.float32)
     return pair
Пример #6
0
    def transform_single(self, sample0):
        sample0 = sample0.copy()
        scale_dim = 1 if self.uniform_scale else 2

        # Draw scale factor
        f_scale = 0.5 + self.rng.randint(0, 11, size=(scale_dim, )) / 10.0

        # Scale the crop size by the inverse of the scale
        sc_size = np.round(self.crop_size_arr / f_scale).astype(int)

        sample0 = self.pad_single(sample0, sc_size)
        image, labels, mask, xf = sample0['image_arr'], sample0.get(
            'labels_arr'), sample0.get('mask_arr'), sample0.get('xf_cv')

        # Randomly choose position
        extra = np.array(image.shape[:2]) - sc_size
        pos = np.round(extra *
                       self.rng.uniform(0.0, 1.0, size=(2, ))).astype(int)

        # Extract crop and scale to target size
        image = image[pos[0]:pos[0] + sc_size[0], pos[1]:pos[1] + sc_size[1]]
        sample0['image_arr'] = cv2.resize(image,
                                          self.crop_size[::-1],
                                          interpolation=cv2.INTER_LINEAR)

        if labels is not None:
            labels = labels[pos[0]:pos[0] + sc_size[0],
                            pos[1]:pos[1] + sc_size[1]]
            sample0['labels_arr'] = cv2.resize(labels,
                                               self.crop_size[::-1],
                                               interpolation=cv2.INTER_NEAREST)

        if mask is not None:
            mask = mask[pos[0]:pos[0] + sc_size[0], pos[1]:pos[1] + sc_size[1]]
            sample0['mask_arr'] = cv2.resize(mask,
                                             self.crop_size[::-1],
                                             interpolation=cv2.INTER_LINEAR)

        if xf is not None:
            # Matching `cv2.resize` requires:
            # - scale factor of out_size/in_size
            # - a translation of (scale_factor - 1) / 2
            scale_factor_yx = self.crop_size_arr / sc_size
            resize_xlat_yx = (scale_factor_yx - 1.0) * 0.5
            sample0['xf_cv'] = affine.cat_nx2x3(
                affine.translation_matrices(
                    resize_xlat_yx[None, ::-1].astype(float)),
                affine.scale_matrices(scale_factor_yx[None, ::-1]),
                affine.translation_matrices(-pos[None, ::-1].astype(float)),
                xf[None, ...])[0]

        return sample0
Пример #7
0
    def transform_pair(self, sample0, sample1):
        sample0 = sample0.copy()
        sample1 = sample1.copy()

        # Flip flags
        flip_flags_xyd = self.rng.binomial(1, 0.5, size=(2, 3)) != 0
        flip_flags_xyd = flip_flags_xyd & np.array(
            [[self.hflip, self.vflip, self.hvflip]])

        sample0['image_arr'] = self.flip_image(sample0['image_arr'],
                                               flip_flags_xyd[0])
        sample1['image_arr'] = self.flip_image(sample1['image_arr'],
                                               flip_flags_xyd[1])

        if 'mask_arr' in sample0:
            sample0['mask_arr'] = self.flip_image(sample0['mask_arr'],
                                                  flip_flags_xyd[0])
            sample1['mask_arr'] = self.flip_image(sample1['mask_arr'],
                                                  flip_flags_xyd[1])

        if 'labels_arr' in sample0:
            sample0['labels_arr'] = self.flip_image(sample0['labels_arr'],
                                                    flip_flags_xyd[0])
            sample1['labels_arr'] = self.flip_image(sample1['labels_arr'],
                                                    flip_flags_xyd[1])

        if 'xf_cv' in sample0:
            # False -> 1, True -> -1
            flip_scale_xy = flip_flags_xyd[:, :2] * -2 + 1
            # Negative scale factors need to be combined with a translation whose value is (image_size - 1)
            # Mask the translation with the flip flags to only apply it where flipping is done
            flip_xlat_xy = flip_flags_xyd[:, :2] * (np.array([
                sample0['image_arr'].shape[:2][::-1],
                sample1['image_arr'].shape[:2][::-1]
            ]).astype(float) - 1)

            hv_flip_xf = affine.identity_xf(2)
            hv_flip_xf[flip_flags_xyd[:, 2]] = hv_flip_xf[
                flip_flags_xyd[:, 2], ::-1, :]

            xf01 = np.stack([sample0['xf_cv'], sample1['xf_cv']], axis=0)
            xf01 = affine.cat_nx2x3(
                hv_flip_xf,
                affine.translation_matrices(flip_xlat_xy),
                affine.scale_matrices(flip_scale_xy),
                xf01,
            )
            sample0['xf_cv'] = xf01[0]
            sample1['xf_cv'] = xf01[1]

        return (sample0, sample1)
Пример #8
0
    def pad_single(self, sample, min_size):
        sample = sample.copy()
        image = sample['image_arr']
        # image, labels, mask, xf = seg_img.image, seg_img.labels, seg_img.mask, seg_img.xf
        img_size = image.shape[:2]
        if img_size[0] < min_size[0] or img_size[1] < min_size[1]:
            # Padding required

            # Compute padding
            pad_h = max(min_size[0] - img_size[0], 0)
            pad_w = max(min_size[1] - img_size[1], 0)
            h0 = pad_h // 2
            h1 = pad_h - h0
            w0 = pad_w // 2
            w1 = pad_w - w0

            # Add an alpha channel to the image so that we can use it during standardisation
            # to ensure that the padding area has a value of 0, post mean-subtraction
            alpha_channel = np.ones(img_size + (1, ), dtype=image.dtype) * 255
            image = np.append(image[:, :, :3], alpha_channel, axis=2)

            # Apply
            sample['image_arr'] = np.pad(image, [[h0, h1], [w0, w1], [0, 0]],
                                         mode='constant',
                                         constant_values=0)
            if 'labels_arr' in sample:
                sample['labels_arr'] = np.pad(sample['labels_arr'],
                                              [[h0, h1], [w0, w1]],
                                              mode='constant',
                                              constant_values=255)
            if 'mask_arr' in sample:
                sample['mask_arr'] = np.pad(sample['mask_arr'],
                                            [[h0, h1], [w0, w1]],
                                            mode='constant')
            if 'xf_cv' in sample:
                sample['xf_cv'] = affine.cat_nx2x3(
                    affine.translation_matrices(np.array([[w0, h0]])),
                    sample['xf_cv'][None, ...])[0]
        return sample
Пример #9
0
 def transform_single(self, sample):
     sample = self.pad_single(sample, self.crop_size)
     image = sample['image_arr']
     extra = np.array(image.shape[:2]) - self.crop_size
     pos = np.round(extra *
                    self.rng.uniform(0.0, 1.0, size=(2, ))).astype(int)
     sample['image_arr'] = image[pos[0]:pos[0] + self.crop_size[0],
                                 pos[1]:pos[1] + self.crop_size[1]]
     if 'labels_arr' in sample:
         sample['labels_arr'] = sample['labels_arr'][pos[0]:pos[0] +
                                                     self.crop_size[0],
                                                     pos[1]:pos[1] +
                                                     self.crop_size[1]]
     if 'mask_arr' in sample:
         sample['mask_arr'] = sample['mask_arr'][pos[0]:pos[0] +
                                                 self.crop_size[0],
                                                 pos[1]:pos[1] +
                                                 self.crop_size[1]]
     if 'xf_cv' in sample:
         sample['xf_cv'] = affine.cat_nx2x3(
             affine.translation_matrices(-pos[None, ::-1].astype(float)),
             sample['xf_cv'][None, ...])[0]
     return sample
Пример #10
0
def paired_transform_ocv(image, transform, output_size, block_size=(1, 1)):
    transform = seg_transforms.SegTransformCompose([
        transform,
        datapipe.seg_transforms_cv.SegCVTransformNormalizeToTensor(None, None)
    ])
    pipe = seg_transforms.SegDataPipeline(block_size, transform)

    x0, m0, xf0, x1, m1, xf1 = pipe.prepare_unsupervised_paired_batch([image])

    x0 = x0[0].transpose(1, 2, 0)
    m0 = m0[0, 0]
    x1 = x1[0].transpose(1, 2, 0)
    m1 = m1[0, 0]

    xf0_to_1 = affine.cat_nx2x3(xf1, affine.inv_nx2x3(xf0))

    image_f = img_as_float(image).astype(np.float32)

    cv0 = cv2.warpAffine(image_f, xf0[0], output_size[::-1])
    cv1 = cv2.warpAffine(image_f, xf1[0], output_size[::-1])
    x01 = cv2.warpAffine(x0, xf0_to_1[0], output_size[::-1])
    m01 = cv2.warpAffine(m0, xf0_to_1[0], output_size[::-1]) * m1

    return dict(x0=x0, cv0=cv0, x1=x1, cv1=cv1, x01=x01, m01=m01)
Пример #11
0
def paired_transform_torch(image, transform, output_size, block_size=(1, 1)):
    transform = seg_transforms.SegTransformCompose([
        transform,
        datapipe.seg_transforms_cv.SegCVTransformNormalizeToTensor(None, None)
    ])
    pipe = seg_transforms.SegDataPipeline(block_size, transform)

    torch_device = torch.device('cpu')

    x0, m0, xf0, x1, m1, xf1 = pipe.prepare_unsupervised_paired_batch([image])

    padded_shape = x0.shape[2:4]

    xf0_to_1 = affine.cat_nx2x3(xf1, affine.inv_nx2x3(xf0))

    t_image_xf0 = affine.cv_to_torch(xf0, padded_shape, image.shape[:2])
    t_image_xf1 = affine.cv_to_torch(xf1, padded_shape, image.shape[:2])
    t_xf0_to_1 = affine.cv_to_torch(xf0_to_1, padded_shape)

    image_f = img_as_float(image).astype(np.float32)

    t_image = torch.tensor(image_f.transpose(2, 0, 1)[None, ...],
                           dtype=torch.float,
                           device=torch_device)
    t_x0 = torch.tensor(x0, dtype=torch.float, device=torch_device)
    t_m0 = torch.tensor(m0, dtype=torch.float, device=torch_device)
    t_m1 = torch.tensor(m1, dtype=torch.float, device=torch_device)
    t_image_xf0 = torch.tensor(t_image_xf0,
                               dtype=torch.float,
                               device=torch_device)
    t_image_xf1 = torch.tensor(t_image_xf1,
                               dtype=torch.float,
                               device=torch_device)
    t_xf0_to_1 = torch.tensor(t_xf0_to_1,
                              dtype=torch.float,
                              device=torch_device)

    output_shape = torch.Size(len(x0), 3, output_size[0], output_size[1])
    grid_image0 = F.affine_grid(t_image_xf0, output_shape)
    grid_image1 = F.affine_grid(t_image_xf1, output_shape)
    grid_0to1 = F.affine_grid(t_xf0_to_1, output_shape)

    t_a = F.grid_sample(t_image, grid_image0)
    t_b = F.grid_sample(t_image, grid_image1)
    t_x01 = F.grid_sample(t_x0, grid_0to1)
    t_m01 = F.grid_sample(t_m0, grid_0to1) * t_m1

    t_a_np = t_a.detach().cpu().numpy()[0].transpose(1, 2, 0)
    t_b_np = t_b.detach().cpu().numpy()[0].transpose(1, 2, 0)
    t_x01_np = t_x01.detach().cpu().numpy()[0].transpose(1, 2, 0)
    t_m01_np = t_m01.detach().cpu().numpy()[0].transpose(1, 2, 0)

    x0 = x0[0].transpose(1, 2, 0)
    x1 = x1[0].transpose(1, 2, 0)

    return dict(x0=x0,
                torch0=t_a_np,
                x1=x1,
                torch1=t_b_np,
                x01=t_x01_np,
                m01=t_m01_np[:, :, 0])
Пример #12
0
    def transform_pair(self, sample0, sample1):
        sample0 = sample0.copy()
        sample1 = sample1.copy()

        # Choose scales and rotations
        if self.constrain_rot_scale:
            if self.uniform_scale:
                scale_factors_yx = np.exp(
                    self.rng.uniform(-self.log_max_scale,
                                     self.log_max_scale,
                                     size=(1, 1)))
                scale_factors_yx = np.repeat(scale_factors_yx, 2, axis=1)
            else:
                scale_factors_yx = np.exp(
                    self.rng.uniform(-self.log_max_scale,
                                     self.log_max_scale,
                                     size=(1, 2)))

            rot_thetas = self.rng.uniform(-self.rot_mag_rad,
                                          self.rot_mag_rad,
                                          size=(1, ))
            scale_factors_yx = np.repeat(scale_factors_yx, 2, axis=0)
            rot_thetas = np.repeat(rot_thetas, 2, axis=0)
        else:
            if self.uniform_scale:
                scale_factors_yx = np.exp(
                    self.rng.uniform(-self.log_max_scale,
                                     self.log_max_scale,
                                     size=(2, 1)))
                scale_factors_yx = np.repeat(scale_factors_yx, 2, axis=1)
            else:
                scale_factors_yx = np.exp(
                    self.rng.uniform(-self.log_max_scale,
                                     self.log_max_scale,
                                     size=(2, 2)))
            rot_thetas = self.rng.uniform(-self.rot_mag_rad,
                                          self.rot_mag_rad,
                                          size=(2, ))

        img_size = np.array(sample0['image_arr'].shape[:2])

        # Scale the crop size by the inverse of the scale
        sc_size = self.crop_size_arr / scale_factors_yx.min(axis=0)
        crop_centre_pos = np.minimum(sc_size, img_size) * 0.5

        # Randomly choose centres
        extra = np.maximum(img_size - sc_size, 0.0)
        centre0 = extra * self.rng.uniform(0.0, 1.0,
                                           size=(2, )) + crop_centre_pos
        offset1 = np.round(self.crop_offset *
                           self.rng.uniform(-1.0, 1.0, size=(2, )))
        centre_xlat = np.stack([centre0, centre0], axis=0)
        offset1_xlat = np.stack([np.zeros((2, )), offset1], axis=0)

        # Build affine transformation matrices
        local_xfs = affine.cat_nx2x3(
            affine.translation_matrices(self.crop_size_arr[None, ::-1] * 0.5),
            affine.translation_matrices(offset1_xlat[:, ::-1]),
            affine.rotation_matrices(rot_thetas),
            affine.scale_matrices(scale_factors_yx[:, ::-1]),
            affine.translation_matrices(-centre_xlat[:, ::-1]),
        )

        # Use nearest neighbour sampling to stay consistent with labels, if labels present
        interpolation = cv2.INTER_NEAREST if 'labels_arr' in sample0 else cv2.INTER_LINEAR
        sample0['image_arr'] = cv2.warpAffine(
            sample0['image_arr'],
            local_xfs[0],
            self.crop_size[::-1],
            flags=interpolation,
            borderValue=0,
            borderMode=cv2.BORDER_REFLECT_101)
        sample1['image_arr'] = cv2.warpAffine(
            sample1['image_arr'],
            local_xfs[1],
            self.crop_size[::-1],
            flags=interpolation,
            borderValue=0,
            borderMode=cv2.BORDER_REFLECT_101)

        if 'labels_arr' in sample0:
            sample0['labels_arr'] = cv2.warpAffine(
                sample0['labels_arr'],
                local_xfs[0],
                self.crop_size[::-1],
                flags=cv2.INTER_NEAREST,
                borderValue=255,
                borderMode=cv2.BORDER_CONSTANT)
            sample1['labels_arr'] = cv2.warpAffine(
                sample1['labels_arr'],
                local_xfs[1],
                self.crop_size[::-1],
                flags=cv2.INTER_NEAREST,
                borderValue=255,
                borderMode=cv2.BORDER_CONSTANT)

        if 'mask_arr' in sample0:
            sample0['mask_arr'] = cv2.warpAffine(
                sample0['mask_arr'],
                local_xfs[0],
                self.crop_size[::-1],
                flags=interpolation,
                borderValue=0,
                borderMode=cv2.BORDER_CONSTANT)
            sample1['mask_arr'] = cv2.warpAffine(
                sample1['mask_arr'],
                local_xfs[1],
                self.crop_size[::-1],
                flags=interpolation,
                borderValue=0,
                borderMode=cv2.BORDER_CONSTANT)

        if 'xf_cv' in sample0:
            xf01 = affine.cat_nx2x3(
                local_xfs,
                np.stack([sample0['xf_cv'], sample1['xf_cv']], axis=0))
            sample0['xf_cv'] = xf01[0]
            sample1['xf_cv'] = xf01[1]

        return (sample0, sample1)
Пример #13
0
    def transform_single(self, sample0):
        sample0 = sample0.copy()

        # Extract contents
        image = sample0['image_arr']

        # Choose scale and rotation
        if self.uniform_scale:
            scale_factor_yx = np.exp(
                self.rng.uniform(-self.log_max_scale,
                                 self.log_max_scale,
                                 size=(1, )))
            scale_factor_yx = np.repeat(scale_factor_yx, 2, axis=0)
        else:
            scale_factor_yx = np.exp(
                self.rng.uniform(-self.log_max_scale,
                                 self.log_max_scale,
                                 size=(2, )))
        rot_theta = self.rng.uniform(-self.rot_mag_rad,
                                     self.rot_mag_rad,
                                     size=(1, ))

        # Scale the crop size by the inverse of the scale
        sc_size = self.crop_size_arr / scale_factor_yx

        # Randomly choose centre
        img_size = np.array(image.shape[:2])
        extra = np.maximum(img_size - sc_size, 0.0)
        centre = extra * self.rng.uniform(0.0, 1.0, size=(2, )) + np.minimum(
            sc_size, img_size) * 0.5

        # Build affine transformation matrix
        local_xf = affine.cat_nx2x3(
            affine.translation_matrices(self.crop_size_arr[None, ::-1] * 0.5),
            affine.rotation_matrices(rot_theta),
            affine.scale_matrices(scale_factor_yx[None, ::-1]),
            affine.translation_matrices(-centre[None, ::-1]),
        )

        # Reflect the image
        # Use nearest neighbour sampling to stay consistent with labels, if labels present
        if 'labels_arr' in sample0:
            interpolation = cv2.INTER_NEAREST
        else:
            interpolation = self.rng.choice(
                [cv2.INTER_NEAREST, cv2.INTER_LINEAR])

        sample0['image_arr'] = cv2.warpAffine(
            image,
            local_xf[0],
            self.crop_size[::-1],
            flags=interpolation,
            borderValue=0,
            borderMode=cv2.BORDER_REFLECT_101)

        # Don't reflect labels and mask
        if 'labels_arr' in sample0:
            sample0['labels_arr'] = cv2.warpAffine(
                sample0['labels_arr'],
                local_xf[0],
                self.crop_size[::-1],
                flags=cv2.INTER_NEAREST,
                borderValue=255,
                borderMode=cv2.BORDER_CONSTANT)

        if 'mask_arr' in sample0:
            sample0['mask_arr'] = cv2.warpAffine(
                sample0['mask_arr'],
                local_xf[0],
                self.crop_size[::-1],
                flags=interpolation,
                borderValue=0,
                borderMode=cv2.BORDER_CONSTANT)

        if 'xf_cv' in sample0:
            sample0['xf_cv'] = affine.cat_nx2x3(local_xf,
                                                sample0['xf_cv'][None, ...])[0]

        return sample0
Пример #14
0
    def transform_pair(self, sample0, sample1):
        sample0 = sample0.copy()
        sample1 = sample1.copy()

        scale_dim = 1 if self.uniform_scale else 2

        # Draw a scale factor for the second crop (crop1 from crop0,crop1)
        f_scale1 = 0.5 + self.rng.randint(0, 11, size=(scale_dim, )) / 10.0

        # Scale the crop size by the inverse of the scale
        sc_size1 = np.round(self.crop_size_arr / f_scale1).astype(int)
        # Compute the maximum crop size that we need
        max_sc_size = np.maximum(self.crop_size_arr, sc_size1)

        # Pad the image if necessary
        sample0, sample1 = self.pad_pair(sample0, sample1, max_sc_size)

        # Randomly choose positions of each crop
        extra = np.array(sample0['image_arr'].shape[:2]) - max_sc_size
        pos0 = np.round(extra *
                        self.rng.uniform(0.0, 1.0, size=(2, ))).astype(int)
        pos1 = pos0 + np.round(self.crop_offset * self.rng.uniform(
            -1.0, 1.0, size=(2, ))).astype(int)
        # Ensure pos1 cannot go out of bounds
        pos1 = np.clip(pos1, np.array([0, 0]), extra)

        centre0 = pos0 + max_sc_size * 0.5
        centre1 = pos1 + max_sc_size * 0.5

        pos0 = np.round(centre0 - self.crop_size_arr * 0.5).astype(int)
        pos1 = np.round(centre1 - sc_size1 * 0.5).astype(int)

        # Extract crop and scale to target size
        sample0['image_arr'] = sample0['image_arr'][pos0[0]:pos0[0] +
                                                    self.crop_size_arr[0],
                                                    pos0[1]:pos0[1] +
                                                    self.crop_size_arr[1]]
        sample1['image_arr'] = sample1['image_arr'][pos1[0]:pos1[0] +
                                                    sc_size1[0],
                                                    pos1[1]:pos1[1] +
                                                    sc_size1[1]]
        # image0 = cv2.resize(image0, self.crop_size[::-1], interpolation=cv2.INTER_LINEAR)
        sample1['image_arr'] = cv2.resize(sample1['image_arr'],
                                          self.crop_size[::-1],
                                          interpolation=cv2.INTER_LINEAR)

        if 'mask_arr' in sample0:
            sample0['mask_arr'] = sample0['mask_arr'][pos0[0]:pos0[0] +
                                                      self.crop_size_arr[0],
                                                      pos0[1]:pos0[1] +
                                                      self.crop_size_arr[1]]
            sample1['mask_arr'] = sample1['mask_arr'][pos1[0]:pos1[0] +
                                                      sc_size1[0],
                                                      pos1[1]:pos1[1] +
                                                      sc_size1[1]]
            # mask0 = cv2.resize(mask0, self.crop_size[::-1], interpolation=cv2.INTER_NEAREST)
            sample1['mask_arr'] = cv2.resize(sample1['mask_arr'],
                                             self.crop_size[::-1],
                                             interpolation=cv2.INTER_NEAREST)

        if 'labels_arr' in sample0:
            sample0['labels_arr'] = sample0['labels_arr'][
                pos0[0]:pos0[0] + self.crop_size_arr[0],
                pos0[1]:pos0[1] + self.crop_size_arr[1]]
            sample1['labels_arr'] = sample1['labels_arr'][pos1[0]:pos1[0] +
                                                          sc_size1[0],
                                                          pos1[1]:pos1[1] +
                                                          sc_size1[1]]
            # labels0 = cv2.resize(labels0, self.crop_size[::-1], interpolation = cv2.INTER_NEAREST)
            sample1['labels_arr'] = cv2.resize(sample1['labels_arr'],
                                               self.crop_size[::-1],
                                               interpolation=cv2.INTER_NEAREST)

        if 'xf_cv' in sample0:
            xf01 = np.stack([sample0['xf_cv'], sample1['xf_cv']], axis=0)

            positions_xy = np.append(pos0[None, ::-1],
                                     pos1[None, ::-1],
                                     axis=0)
            # Matching `cv2.resize` requires:
            # - scale factor of out_size/in_size
            # - a translation of (scale_factor - 1) / 2
            scale_factors_xy = np.append(
                np.array([[1, 1]]),
                self.crop_size_arr[None, ::-1].astype(float) /
                sc_size1[None, ::-1],
                axis=0)
            resize_xlats_xy = (scale_factors_xy - 1.0) * 0.5

            xf01 = affine.cat_nx2x3(
                affine.translation_matrices(resize_xlats_xy),
                affine.scale_matrices(scale_factors_xy),
                affine.translation_matrices(-positions_xy),
                xf01,
            )
            sample0['xf_cv'] = xf01[0]
            sample1['xf_cv'] = xf01[1]

        return sample0, sample1