Exemple #1
0
    def _set_cut_mask(self, mask, size):
        """
        Manages the cut mask for the destination image, if present.
         The mask is turned into a binary image of the same size of the
         destination image.

        Args:
            mask: mask of the destination image
            size: size of the destination image

        Returns:
            mask of the destination image
        """
        if mask is None:
            self.log.debug('Ymask: None')
            return

        # 1 channel
        if len(mask.shape) == 3:
            mask = rgb2gray(mask)
        elif not len(mask.shape) == 2:
            raise ValueError('Input mask must be 2 or 3 dimensional')

        # resize it according to size
        mask = im2double(imresize(mask, size=size))

        # binary values
        mask[mask < 0.01] = 0
        mask[mask > 0] = 1

        self.log.debug('Ymask: {0}'.format(mask.shape))
        return mask
Exemple #2
0
    def test_distance_candidates(self):
        """
        Test that all the candidates are good choices.
        """
        # eye matrix
        img = -np.eye(10) * 2 + 1
        img = np.asarray(np.dstack((img, img, img)))
        # parch is similar to a submatrix of img
        patch = np.asarray([[1, 1, 1, 1.], [1, 1, 1, 1.], [-1, 1, 0, 0.],
                            [1, -1, 0, 0.]])
        patch = im2double(gray2rgb(patch))

        # compute distance
        q = Quilt(img, output_size=[20, 20])
        distances = q.distance(patch, tilesize=4, overlap=2, coord=[2, 2])
        best = np.min(distances)
        candidates = np.where(distances <= best)

        # submatrix of img similar to patch
        expected = np.asarray([[1, 1, 1, 1], [1, 1, 1, 1], [-1, 1, 1, 1],
                               [1, -1, 1, 1]])
        for i in range(len(candidates[0])):
            sub = [candidates[0][i], candidates[1][i]]
            result = img[sub[0]:sub[0] + 4, sub[1]:sub[1] + 4, 1]
            assert_array_equal(expected, result)
Exemple #3
0
    def test_distance_submatrix(self):
        """
        Test distance computation. Test a submatrix is found inside a bigger
        matrix.
        """
        img = np.array([[64, 2, 3, 61, 60, 6, 7, 57],
                        [9, 55, 54, 12, 13, 51, 50, 16],
                        [17, 47, 46, 20, 21, 43, 42, 24],
                        [40, 26, 27, 37, 1, 1, 1, 33],
                        [32, 34, 35, 29, 1, 1, 1, 25],
                        [41, 23, 22, 44, 1, 1, 1, 48],
                        [49, 15, 14, 52, 53, 11, 10, 56]])
        img = np.uint8(gray2rgb(img))
        patch = np.array([[26, 27, 37], [34, 35, 29], [23, 22, 44]])
        patch = im2double(np.uint8(gray2rgb(patch)))

        q = Quilt(img, output_size=[20, 20])
        result = q.distance(patch, tilesize=3, overlap=2, coord=[1, 1])
        expected = zeros((5, 6))
        self.assertEqual(expected.shape, result.shape)

        # check where the min is
        arg_min = np.where(result == np.min(result))
        expected = np.asarray([[3], [1]])
        assert_array_equal(expected, arg_min)
Exemple #4
0
    def test_im2double_uint8(self):
        """
        Test im2double behaviour when given a matrix with uint8 values.
        """
        float_a = np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])
        int_a = np.uint8(float_a * 255)
        result = im2double(int_a)

        self.assertEqual('float', result.dtype)

        # round at the first decimal
        expected = float_a
        assert_array_equal(expected, np.around(result, decimals=1))
Exemple #5
0
    def test_src_size(self):
        """
        Test the source image is turned to rgb float and is not reshaped.
        """
        q = Quilt(self.x, output_size=self.x.shape)

        # there is just one image in the stack
        self.assertEqual(1, len(q.X))
        # rgb
        assert_array_equal((self.x.shape[0], self.x.shape[1], 3), q.X[0].shape)
        # float
        self.assertEqual('float', q.X[0].dtype)

        expected = gray2rgb(im2double(self.x))
        assert_array_equal(expected, q.X[0])
Exemple #6
0
    def _set_src(self, img, rotate=0, flip=None):
        """
        Manages source image/s:
            - turns it into a stack of images of the same size
            - images are set to float values in range [0, 1]
            - rotated images are added if required
        Args:
            img: source image/s: can be a single image or a stack of images of
                 the same size
            rotate: number of 90 degrees rotations to apply to each image in
                    the stack.
            flip: list of two booleans for [flip_vertical, flip_horizontal]

        Returns:
            - reference image (the first image of the stack with no rotations)
            - stack of the source images
        """
        # stack of images
        if not isinstance(img, list):
            img = [img]

        reference = None
        for i in xrange(len(img)):
            # images in the stack must have the same size
            if i and not img[i].shape[0:2] == img[0].shape[0:2]:
                raise ValueError('Chained images must have the same size. Got '
                                 '{0} and {1}'.format(img[i].shape[0:2],
                                                      img[0].shape[0:2]))
            # 3 channel images
            img[i] = gray2rgb(img[i])
            # float values in range [0, 1]
            img[i] = im2double(img[i])
            if not i:
                reference = img[i]
        # rotation
        img = [self.create_rotations(i, rotate) for i in img]
        img = [self.create_flip(i, flip) for i in img]

        return reference, img
Exemple #7
0
    def test_stack(self):
        """
        Test the the source images are edited consistently and a same number of
        destination images is prepared.
        """
        q = Quilt([self.x, self.x, self.x], output_size=[30, 20])

        # there are 3 images in the stacks
        expected_x = gray2rgb(im2double(self.x))
        expected_y = zeros((30, 20, 3))
        self.assertEqual(3, len(q.X))
        self.assertEqual(3, len(q.Y))

        for i in xrange(3):
            # src
            assert_array_equal((self.x.shape[0], self.x.shape[1], 3),
                               q.X[i].shape)
            self.assertEqual('float', q.X[i].dtype)
            assert_array_equal(expected_x, q.X[i])

            # dst
            assert_array_equal((30, 20, 3), q.Y[i].shape)
            assert_array_equal(expected_y, q.Y[i])
Exemple #8
0
    def _set_src_mask(self,
                      mask,
                      tilesize,
                      reference=None,
                      rotate=0,
                      flip=(0, 0)):
        """
        Manages the mask of the source image (if present):
            - checks the mask has the same size of the source image
            - turns it into a 1-channel image with values in {0, infinite}
            - expands masked areas:
              for every masked (= white) pixel: all the pixels tilesize-distant
              from it are masked. In this way all the tiles containing that
              pixel are removed. This is used in the calculation of the
              convolution between a patch and the source image.

        Args:
            mask: input mask
            reference: master source image without rotation
            rotate: number of 90 degrees rotations to be applied to the mask
            flip: tuple of two flag controlling flip transformations

        Returns:
            mask
        """
        # no mask
        if mask is None:
            if not rotate and flip == (0, 0):
                self.log.debug('Xmask: None')
                return
            # create the mask to remove the lines between the rotations
            mask = ones(reference.shape[0:2])

        # coherent with reference
        if reference is None:
            reference = self.X
        if not mask.shape[0:2] == reference.shape[0:2]:
            raise ValueError('X and Xmask cannot have different sizes:'
                             'X={0} Xmask={1}'.format(reference.shape,
                                                      mask.shape))
        # one channel image
        mask = rgb2gray(mask)

        # rotate
        mask = self.create_rotations(mask, rotate)
        mask = self.create_flip(mask, flip)

        # values in {0, inf}
        mask = im2double(mask)
        mask[mask < 0.7] = inf
        mask[mask <= 1] = 0

        # expand masked values:
        # if there is a mask on the input: remove all the points leading to
        # patches with an overlap on that area. i.e.: mask the area and
        # anything a tile-size distant on the left or top.
        # The mask will be summed to the convolution result. Doing so, when
        # searching the min of the convolution, masked areas will not be
        # considered since their value is infinite.

        # change overlap?
        for i in xrange(mask.shape[0] - self.overlap + 1):
            for j in xrange(mask.shape[1] - self.overlap + 1):
                # get the tile starting from the pixel
                tile = mask[i:i + tilesize, j:j + tilesize]
                # if it contains a masked value: also the pixel generating the
                # tile has to be masked
                if np.any(tile == inf):
                    mask[i, j] = inf

        self.log.debug('Xmask: {0} values: {1}'.format(mask.shape,
                                                       np.unique(mask)))
        return mask