def _launch_quilt(debug, final_path, src, **kwargs): """ Launches quilt process with the parsed arguments. """ multi_proc = kwargs.pop('multiprocess') # ------------- quilt -------------- qs = time.time() log.info('Quilt started at {0}'.format(time.strftime("%H:%M:%S"))) try: # compute quilting Quilt.debug = debug q = Quilt(src, **kwargs) if multi_proc: q.optimized_compute() else: q.compute() # get the result result = q.get_result() if debug: show(result) save(result, final_path) except ValueError as err: log.error(err.message) return t = (time.time() - qs) / 60 log.debug('Quilt took {0:0.6f} minutes'.format(t)) log.info('End {0}'.format(time.strftime("%H:%M:%S")))
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)
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)
def compute(self): """ Single, traditional, single process computation. """ self.log.info('\nCOMPUTING ...') for n in xrange(self.niter): for i in xrange(self.num_tiles[0]): startI = i * self.tilesize - i * self.overlap endI = min(self.Y[0].shape[0], startI + self.tilesize) sizeI = endI - startI if sizeI <= self.overlap: continue for j in xrange(self.num_tiles[1]): startJ = j * self.tilesize - j * self.overlap endJ = min(self.Y[0].shape[1], startJ + self.tilesize) sizeJ = endJ - startJ if sizeJ <= self.overlap: continue # skip if this patch is not meant to be filled if self.Ymask and not np.any(self.Ymask[startI:endI, startJ:endJ]): continue # Dist from each tile to the overlap region y_patches = [ y[startI:endI, startJ:endJ, :] for y in self.Y ] res_patches = self._compute_patch( y_patches, [sizeI, sizeJ], (i, j), mask=self.Xmask, constraint_start=self.constraint_start) for idx, res in enumerate(res_patches): self.Y[idx][startI:endI, startJ:endJ, :] = res self.log.debug('iter {0} / {1}'.format(n, self.niter)) show(self.Y[0]) if self.debug else None if self.result_path: save(self.Y[0], self.result_path)
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)
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)