Esempio n. 1
0
 def blend_channel(channel):
     with log_timer("%s.native" % self.__class__.__name__):
         solution = self.cache_native[channel].blend(self.epsilon, self.max_iterations)
     self.cache_target[t_top:t_bottom, t_left:t_right, channel] = solution
     errorlog = self.cache_errorlog[channel]
     LOG.debug("Quickdescent iterations: %d" % (errorlog.nonzero()[0][-1] + 1))
     LOG.debug("Final error value: %f" % (errorlog[errorlog.nonzero()[0][-1]]))
Esempio n. 2
0
    def draw_numpy(self, ndarray):
        """
        Draws a numpy array (H * W * 3) as an image on this canvas.

        """
        assert ndarray.dtype == np.float32
        ndarray = np.clip(ndarray * 255., 0., 255.).astype(np.uint8)
        with log_timer("EditorViewCanvas.draw_numpy"):
            if self.active_image_container is None:
                self.active_image_container = ImageTk.PhotoImage(Image.fromarray(ndarray))
                self.itemconfig(self.active_image_id, image=self.active_image_container)
            else:
                self.active_image_container.paste(Image.fromarray(ndarray))
Esempio n. 3
0
    def get_fusion(self):
        with log_timer("%s.get_fusion" % self.__class__.__name__):
            target = np.copy(self.canvas)
            if not self.active:
                return target

            s_top, s_bottom, s_left, s_right = self.source_bounds
            t_top, t_bottom, t_left, t_right = self.target_bounds
            source = self.active_source[s_top:s_bottom, s_left:s_right]
            tinyt = target[t_top:t_bottom, t_left:t_right, :]
            s_mask = self.active_mask[t_top:t_bottom, t_left:t_right]

            for channel in range(3):
                solution = self.poisson_blend(source[:, :, channel], s_mask, tinyt[:, :, channel])
                target[t_top:t_bottom, t_left:t_right, channel] = solution

            return target
Esempio n. 4
0
    def get_fusion(self):
        with log_timer("%s.get_fusion" % self.__class__.__name__):
            if not self.active:
                return np.copy(self.canvas)

            s_top, s_bottom, s_left, s_right = self.source_bounds
            t_top, t_bottom, t_left, t_right = self.target_bounds

            if (self.source_bounds != self.cache_source_bounds or
                    self.target_bounds != self.cache_target_bounds):
                with log_timer("%s.setup" % self.__class__.__name__):
                    # We copy cache_mask here, because the native code would need to copy it anyway
                    # (since it is a view, not an actual ndarray).  However, we don't copy source or
                    # tinyt, because it is cloned per-channel in the "for channel in range(3)" loop
                    # below.
                    source = self.active_source[s_top:s_bottom, s_left:s_right]
                    tinyt = self.canvas[t_top:t_bottom, t_left:t_right, :]
                    self.cache_mask = np.copy(self.active_mask[t_top:t_bottom, t_left:t_right],
                                              order="C")

                    # Used for storing our QuickdescentContext instances
                    self.cache_native = []

                    # Used for storing all our errorlogs
                    self.cache_errorlog = []

                    # Used for storing the fusion result (we can reuse this buffer)
                    self.cache_target = np.copy(self.canvas)

                    for channel in range(3):
                        solution = np.zeros(tinyt.shape[:2], dtype=np.float32, order="C")
                        errorlog = np.zeros(self.max_iterations, dtype=np.float32, order="C")
                        q = _quickdescent.QuickdescentContext(source[:, :, channel].copy(order="C"),
                                                              self.cache_mask,
                                                              tinyt[:, :, channel].copy(order="C"),
                                                              solution, errorlog)
                        q.initializeGuess()
                        self.cache_native.append(q)
                        self.cache_errorlog.append(errorlog)

                    self.cache_source_bounds = self.source_bounds
                    self.cache_target_bounds = self.target_bounds

            def blend_channel(channel):
                with log_timer("%s.native" % self.__class__.__name__):
                    solution = self.cache_native[channel].blend(self.epsilon, self.max_iterations)
                self.cache_target[t_top:t_bottom, t_left:t_right, channel] = solution
                errorlog = self.cache_errorlog[channel]
                LOG.debug("Quickdescent iterations: %d" % (errorlog.nonzero()[0][-1] + 1))
                LOG.debug("Final error value: %f" % (errorlog[errorlog.nonzero()[0][-1]]))

            if self.threading:
                threads = []
                for channel in range(3):
                    thread = threading.Thread(target=blend_channel, args=(channel,))
                    threads.append(thread)

                for thread in threads:
                    thread.start()

                for thread in threads:
                    thread.join()
            else:
                for channel in range(3):
                    blend_channel(channel)

            return self.cache_target.clip(0, 1)