示例#1
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)
示例#2
0
 def test_show_list(self, mk_show):
     """
     Test show calls _show method in Image just once with the right args.
     Test with a list of images as input.
     """
     a = matrix2img(gray2rgb(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])))
     b = matrix2img(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7], [1, 0.3, 0.7]]))
     c = matrix2img(gray2rgb(np.array([[0.5, 0.8], [0.3, 0.7], [0.3,
                                                                0.7]])))
     show([a, b, c])
     expected = [
         mock.call(a, command=None, title=None),
         mock.call(b, command=None, title=None),
         mock.call(c, command=None, title=None)
     ]
     mk_show.assert_has_calls(expected)
示例#3
0
    def test_imresize_img_size(self):
        """
        Test imresize result when a different size is required.
        """
        img = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
        img = Image.fromarray(gray2rgb(img), 'RGB')

        # bigger
        size = [5, 9]
        result = imresize(img, size)
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(size[::-1], result.size)
        result = imresize(img, height=size[0], width=size[1])
        assert_array_equal(size[::-1], result.size)

        # smaller
        size = [3, 2]
        result = imresize(img, size)
        assert_array_equal(size[::-1], result.size)
        self.assertTrue(isinstance(result, Image.Image))
        result = imresize(img, height=size[0], width=size[1])
        assert_array_equal(size[::-1], result.size)

        # other
        size = [10, 3]
        result = imresize(img, size)
        assert_array_equal(size[::-1], result.size)
        self.assertTrue(isinstance(result, Image.Image))
        result = imresize(img, height=size[0], width=size[1])
        assert_array_equal(size[::-1], result.size)
示例#4
0
    def test_imresize_3Dimg_base(self):
        """
        Test imresize basic behaviour with input image as Image.
        Test the result is consistent if no scale is applied.
        """
        img = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
        img = Image.fromarray(gray2rgb(img), 'RGB')

        # scale
        result = imresize(img, scale=1)
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(img, result)

        # size
        result = imresize(img, [4, 5])
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(img, result)

        # height only
        result = imresize(img, height=4)
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(img, result)

        # width only
        result = imresize(img, width=5)
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(img, result)

        # height and width
        result = imresize(img, height=4, width=5)
        self.assertTrue(isinstance(result, Image.Image))
        assert_array_equal(img, result)
示例#5
0
    def test_imresize_3Dmatrix_base(self):
        """
        Test imresize basic behaviour with input image as matrix.
        Test the result is consistent if no scale is applied.
        """
        img = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
        img = gray2rgb(img)

        # scale
        result = np.around(imresize(img, scale=1), decimals=1)
        self.assertTrue(isinstance(result, np.ndarray))
        assert_array_equal(img, result)

        # size
        result = np.around(imresize(img, [4, 5]), decimals=1)
        self.assertTrue(isinstance(result, np.ndarray))
        assert_array_equal(img, result)

        # height only
        result = np.around(imresize(img, height=4), decimals=1)
        self.assertTrue(isinstance(result, np.ndarray))
        assert_array_equal(img, result)

        # width only
        result = np.around(imresize(img, width=5), decimals=1)
        self.assertTrue(isinstance(result, np.ndarray))
        assert_array_equal(img, result)

        # height and width
        result = np.around(imresize(img, height=4, width=5), decimals=1)
        self.assertTrue(isinstance(result, np.ndarray))
        assert_array_equal(img, result)
示例#6
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)
示例#7
0
 def test_show_single_uint(self, mk_show):
     """
     Test show calls _show method in Image just once.
     Test with a single uint8 image as input.
     """
     a = np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])
     show(np.uint8(gray2rgb(a)))
     mk_show.assert_called_once_with(mock.ANY, command=None, title=None)
示例#8
0
 def test_show_single_float(self, mk_show):
     """
     Test show calls _show method in Image just once with the right args.
     Test with a single float64 image as input.
     """
     a = np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])
     a = matrix2img(gray2rgb(a))
     show(a)
     mk_show.assert_called_once_with(a, command=None, title=None)
示例#9
0
 def test_save_single_matrix(self, mk_save):
     """
     Test save calls the save() method of each input images with the realtive
     paths.
     """
     a = gray2rgb(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]]))
     path = 'custom/path/a.jpg'
     save(a, path)
     mk_save.assert_called_once_with(path)
示例#10
0
    def test_gray2rgb_rgb(self):
        """
        Test gray2rgb behaviour when given a 3-channels matrix.
        """
        a = np.array([[[0, 0, 0], [9, 9, 9], [8, 8, 8]],
                      [[8, 8, 8], [7, 7, 7], [9, 9, 9]]])
        result = gray2rgb(a)

        expected = a
        assert_array_equal(expected, result)
示例#11
0
    def test_save_list_img(self):
        """
        Test save calls the save() method of each input images with the realtive
        paths.
        """
        a = matrix2img(gray2rgb(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])))
        b = matrix2img(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7], [1, 0.3, 0.7]]))
        c = matrix2img(gray2rgb(np.array([[0.5, 0.8], [0.3, 0.7], [0.3,
                                                                   0.7]])))
        a_path = 'custom/path/a.jpg'
        b_path = 'custom/path/b.jpg'
        c_path = 'custom/path/c.jpg'

        with mock.patch.object(a, 'save') as mka:
            with mock.patch.object(b, 'save') as mkb:
                with mock.patch.object(c, 'save') as mkc:
                    save([a, b, c], [a_path, b_path, c_path])
                    mka.assert_called_once_with(a_path)
                    mkb.assert_called_once_with(b_path)
                    mkc.assert_called_once_with(c_path)
示例#12
0
    def create_flip(cls, img, amount=(0, 0)):
        """
        Generates the required flips of the input image and builds an image
        containing the input image and its flips.
        The final image is so composed:
                              _______
        If amount = [0, 1]:  | img   |
                             |_______|
                             | flipV |
                             |_______|
                              _______ _______
        If amount = [1, 0]:  | img   | flipH |
                             |_______|_______|

                              _______ _______
        If amount = [1, 1]:  | img   | flipH |
                             |_______|_______|
                             | flipV |flipHV |
                             |_______|_______|
        Args:
            img: image to be rotated
            amount:
        Returns:
            image composed of the input one and it rotations
        """
        # check the amount
        if not amount or amount == (0, 0):
            return img

        # turn the input image into a 3-channel image
        third_dim = len(img.shape) == 3
        img = gray2rgb(img)

        # vertical
        if amount[0]:
            flip = zeros((img.shape[0] * 2 + 1, img.shape[1], 3))
            flip[:img.shape[0], :, :] = img
            flip[img.shape[0] + 1:, :, :] = flipud(img)
            img = flip

        # horizontal
        if amount[1]:
            flip = zeros((img.shape[0], img.shape[1] * 2 + 1, 3))
            flip[:, :img.shape[1], :] = img
            flip[:, img.shape[1] + 1:, :] = fliplr(img)
            img = flip

        # if the input image had 1 channel only, also the result will do
        if not third_dim:
            img = img[:, :, 0]

        show(img) if cls.debug else None

        return img
示例#13
0
    def test_filter_img(self):
        """
        Test filter_img. Given two images and a mask, test the result is correct
        """
        a = np.array([[30, 39, 48, 1], [38, 47, 7, 9], [46, 6, 8, 17],
                      [5, 14, 16, 25]])
        a = gray2rgb(a)
        b = np.array([[9, 18, 27, 29], [17, 26, 35, 37], [25, 34, 36, 45],
                      [33, 42, 44, 4]])
        b = gray2rgb(b)
        m = np.array([[0, 0, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1], [0, 0, 0, 1]])
        result = filter_img(a, b, m)
        expected = np.asarray([[9, 18, 48, 1], [17, 47, 7, 9], [46, 6, 8, 17],
                               [33, 42, 44, 25]])
        expected = gray2rgb(expected)

        # size
        self.assertEqual(expected.shape, result.shape)
        # values
        np.testing.assert_array_equal(expected, result)
示例#14
0
    def test_save_single_img(self):
        """
        Test save calls the save() method of the input image once and with the
        given path.
        """
        a = matrix2img(gray2rgb(np.array([[0, 0.5, 0.8], [1, 0.3, 0.7]])))
        path = 'custom/path'

        with mock.patch.object(a, 'save') as mk_save:
            save(a, path)
            mk_save.assert_called_once_with(path)
示例#15
0
 def test_img2matrix_3Dmatrix(self):
     """
     Test img2matrix with a 3d matrix as input.
     """
     matrix = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
     matrix = gray2rgb(matrix)
     result = img2matrix(matrix)
     # type
     self.assertTrue(isinstance(result, np.ndarray))
     # dimensions
     assert_array_equal(matrix.shape, result.shape)
     # values
     assert_array_equal(matrix, result)
示例#16
0
 def test_matrix2img_3Dimg(self):
     """
     Test matrix2img with an RGB image as input.
     """
     matrix = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
     img = Image.fromarray(gray2rgb(matrix), 'RGB')
     result = matrix2img(img)
     # type
     self.assertTrue(isinstance(result, Image.Image))
     # dimensions
     assert_array_equal(img.size, result.size)
     # values
     assert_array_equal(img, result)
示例#17
0
 def test_matrix2img_3Dmatrix(self):
     """
     Test matrix2img with a 3d matrix as input.
     """
     matrix = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
     matrix = gray2rgb(matrix)
     result = matrix2img(matrix)
     # type
     self.assertTrue(isinstance(result, Image.Image))
     # dimensions
     assert_array_equal(matrix.shape[0:2][::-1], result.size)
     # values
     expected = np.uint8(matrix * 255)
     assert_array_equal(expected, np.asarray(result))
示例#18
0
 def test_img2matrix_3Dimg(self):
     """
     Test img2matrix with an RGB image as input.
     """
     matrix = np.asarray([[.3, 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
     matrix = gray2rgb(matrix)
     img = matrix2img(matrix)
     result = img2matrix(img)
     # type
     self.assertTrue(isinstance(result, np.ndarray))
     # dimensions
     assert_array_equal(matrix.shape, result.shape)
     # values
     assert_array_equal(matrix, np.around(result, decimals=1))
示例#19
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])
示例#20
0
    def test_imresize_img_scale(self):
        """
        Test imresize result when a different scale is required.
        """
        img = np.asarray([[0., 1., .2, .3, .4], [.5, .8, .7, .8, .9],
                          [1., .0, .2, .3, .4], [.5, .7, .9, .9, .8]])
        img = Image.fromarray(gray2rgb(img), 'RGB')

        # bigger
        result = imresize(img, scale=1.4)
        self.assertTrue(isinstance(result, Image.Image))
        expected_size = (7, 5)
        assert_array_equal(expected_size, result.size)

        # smaller
        result = imresize(img, scale=0.8)
        self.assertTrue(isinstance(result, Image.Image))
        expected_size = (4, 3)
        assert_array_equal(expected_size, result.size)
示例#21
0
    def test_gray2rgb_gray(self):
        """
        Test gray2rgb behaviour when given a mono-channel matrix.
        """
        a = np.array([[0, 9, 8], [8, 7, 9]])
        result = gray2rgb(a)

        # size
        expected_size = (a.shape[0], a.shape[1], 3)
        assert_array_equal(expected_size, result.shape)

        # values are from input
        expected_values = np.unique(a)
        assert_array_equal(expected_values, np.unique(result))

        # test with matrix
        expected = np.array([[[0, 0, 0], [9, 9, 9], [8, 8, 8]],
                             [[8, 8, 8], [7, 7, 7], [9, 9, 9]]])
        assert_array_equal(expected, result)
示例#22
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
示例#23
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])
示例#24
0
    def optimized_compute(self):
        """
        First process: it computes the quilt algorithm with big tiles,
        manages child processes and them combines the results.

         1) creates the child processes (number defined according to the
            available cores and the number of big tiles in the image)
         2) computes quilting with big tiles
         3) every time a tile is computed (and sewed with the image), it is put
            in a queue
        process 1: big tiles
         for each of the tile: process n

        """

        self.log.info('\nMULTIPROCESSING COMPUTING ...')

        big_num_tiles = self.calc_num_tiles(tile_size=self.big_tilesize,
                                            overlap=self.big_overlap)

        # prepare the pool
        n_proc = min(big_num_tiles[0] * big_num_tiles[1], self.cores)
        out_queue = Queue()
        in_queue = JoinableQueue()
        pool = Pool(n_proc, unwrap_self, (
            self,
            in_queue,
            out_queue,
        ))
        self.log.info('preparing {0} processes - {1}'.format(
            n_proc, time.strftime("%H:%M:%S")))

        if self.Ymask is not None:
            # zero values will become inf
            Ymask_rgb = gray2rgb(self.Ymask)
            # use the mask as a draft of the dst img so that boundaries are
            # respected
            self.Y[0] = deepcopy(Ymask_rgb)

        for i in xrange(big_num_tiles[0]):

            startI = i * self.big_tilesize - i * self.big_overlap
            endI = min(self.Y[0].shape[0], startI + self.big_tilesize)
            sizeI = endI - startI
            if sizeI <= self.overlap:
                continue

            for j in xrange(big_num_tiles[1]):

                startJ = j * self.big_tilesize - j * self.big_overlap
                endJ = min(self.Y[0].shape[1], startJ + self.big_tilesize)
                sizeJ = endJ - startJ
                if sizeJ <= self.overlap:
                    continue

                dst_patches = [y[startI:endI, startJ:endJ, :] for y in self.Y]
                # for the big tiles don't consider the mask, since it would
                # remove most of the image because the tiles are so big
                res_patches = self._compute_patch(
                    dst_patches, [sizeI, sizeJ], (i, j),
                    mask=self.Xmask_big,
                    constraint_start=self.constraint_start,
                    err=0.8)

                # add the mask on top
                if self.Ymask is not None:
                    res_patches = [
                        r * Ymask_rgb[startI:endI, startJ:endJ]
                        for r in res_patches
                    ]
                for idx, res in enumerate(res_patches):
                    self.Y[idx][startI:endI, startJ:endJ, :] = res

                # make a process start in this big tile
                _img = [y[startI:endI, startJ:endJ, :] for y in self.Y]
                _mask = self.Ymask[startI:endI, startJ:endJ] \
                    if self.Ymask is not None else None
                _id = (startI, startJ)
                in_queue.put({'dst': _img, 'mask': _mask, 'id': _id})

        # wait for all the children
        self.log.debug('master finished {0}'.format(time.strftime("%H:%M:%S")))
        show(self.Y[0]) if self.debug else None
        pool.close()
        self.log.debug('closed, in queue: {0} out: {1}'.format(
            in_queue.qsize(), out_queue.qsize()))
        in_queue.join()
        self.log.debug('all children finished {0}'.format(
            time.strftime("%H:%M:%S")))

        # get the results
        results = sorted([
            out_queue.get()
            for _ in xrange(big_num_tiles[0] * big_num_tiles[1])
        ])

        # sew them together
        for idx, res in results:

            # calculate the mask
            base_patch = self.Y[0][idx[0]:idx[0] + self.big_tilesize,
                                   idx[1]:idx[1] + self.big_tilesize]
            new_patch = res[0]
            mask_patch = self.calc_patch_mask(base_patch,
                                              new_patch,
                                              coord=idx,
                                              overlap=self.big_overlap)
            # apply the mask to each layer
            for i, y in enumerate(self.Y):
                base_patch = y[idx[0]:idx[0] + self.big_tilesize,
                               idx[1]:idx[1] + self.big_tilesize]
                new_patch = res[i]
                self.Y[i][idx[0]:idx[0]+self.big_tilesize,
                          idx[1]:idx[1]+self.big_tilesize, :] = \
                    filter_img(new_patch, base_patch, mask_patch)

        # apply the mask again
        if self.Ymask is not None:
            self.Y = [r * Ymask_rgb for r in self.Y]

        show(self.Y[0]) if self.debug else None
        if self.result_path:
            save(self.Y[0], self.result_path)
            self.log.info('saving' + self.result_path)
示例#25
0
    def create_rotations(cls, img, amount):
        """
        Generates the required rotations of the input image and builds an image
        containing the input image and its rotations (the remaining space is
        left zero). The final image is so composed:
                          _______
        If amount == 2:  | rot0  |
                         |_______|
                         |rot180 |
                         |_______|
                          _______ _____ _____
        If amount == 4:  | rot0  |     |     |
                         |_______| rot | rot |
                         |rot180 | 90  | -90 |
                         |_______|_____|_____|
        Args:
            img: image to be rotated
            amount: amount of rotation of 90 degrees.
                    E.g.: amount = 2 --> rotation = 90*2 = 180
                    Accepted values: {0, 2, 4}
        Returns:
            image composed of the input one and it rotations
        """
        # check the amount
        if not amount:
            return img
        if amount not in [2, 4]:
            raise ValueError(
                'Rotation must be None, 2 or 4. Got {0}'.format(amount))

        # turn the input image into a 3-channel image
        third_dim = len(img.shape) == 3
        img = gray2rgb(img)

        rot = None
        if amount == 2:
            rot = zeros((img.shape[0] * 2 + 1, img.shape[1], 3))
            rot[:img.shape[0], :, :] = img
            rot[img.shape[0] + 1:, :, :] = rot90(img, 2)

        if amount == 4:
            # set so that height > width
            if img.shape[0] > img.shape[1]:
                img = rot90(img, 1)

            rot = zeros((max(img.shape[1], img.shape[0] * 2 + 1),
                         img.shape[1] + img.shape[0] * 2 + 2, 3))
            rot[:img.shape[0], :img.shape[1], :] = img
            rot[img.shape[0] + 1: img.shape[0] * 2 + 1, :img.shape[1], :] = \
                rot90(img, 2)
            rot[:img.shape[1],
                img.shape[1] + 1:img.shape[1] + 1 + img.shape[0], :] = rot90(
                    img, 1)
            rot[:img.shape[1], img.shape[0] + img.shape[1] + 2:, :] = \
                rot90(img, 3)

        # if the input image had 1 channel only, also the result will do
        if not third_dim:
            rot = rot[:, :, 0]

        show(rot) if cls.debug else None

        return rot