Beispiel #1
0
    def __init__(self, algorithm="reference", algorithm_kwargs=None):
        """This is the View that renders the main editor window."""
        if algorithm_kwargs is None:
            algorithm_kwargs = {}

        self.root = tk.Tk()
        self.root.wm_title("Streaming Gradient Domain Fusion")
        self.frame = EditorViewFrame(self.root)

        # Set up editor canvas
        self.target_canvas = EditorViewCanvas(self.frame, background="#009900",
                                              highlightthickness=0)
        self.target_canvas.bind("<Button-1>", self.handle_loadtarget)
        self.source_canvas = EditorViewCanvas(self.frame, background="#00477d",
                                              highlightthickness=0)
        self.source_canvas.bind("<Button-1>", self.handle_loadsource)
        self.frame.register_canvas_set(self.target_canvas, self.source_canvas)
        self.target_canvas.grid(row=0, column=1)
        self.source_canvas.grid(row=0, column=2)

        # Set up editor menu
        menu_items = OrderedDict()
        menu_items["File"] = [("Load target image", self.handle_loadtarget, (SUPER, "o")),
                              ("Load source image", self.handle_loadsource, (SUPER, SHIFT, "o")),
                              ("Save canvas", self.handle_save, (SUPER, "s")),
                              (),
                              ("Close", self.handle_quit, (SUPER, "w"))]
        menu_items["Edit"] = [("Undo", self.handle_unimplemented, (SUPER, "z"))]
        menu_items["Brush"] = [("Square",
                                lambda: self.set_brush_circular(False), (SUPER, "1")),
                               ("Circle",
                                lambda: self.set_brush_circular(True), (SUPER, "2")),
                               ("Feathered",
                                lambda: self.set_brush_feathered(True), (SUPER, "3")),
                               ("Not Feathered",
                                lambda: self.set_brush_feathered(False), (SUPER, "4")),
                               (),
                               ("Increase brush size", self.increase_brush_size, (CONTROL, "bracketright")),
                               ("Decrease brush size", self.decrease_brush_size, (CONTROL, "bracketleft"))]
        menu_items["Help"] = []
        self.menu = MenuBuilder(items=menu_items)
        self.menu.render(self.root)

        # Set up editor window
        self.frame.pack(fill=tk.BOTH, expand=tk.YES)
        self.root.geometry("1200x500")
        self.fusion = get_fusion_algorithm(algorithm)(**algorithm_kwargs)
        self.mask_ndarray = None
        self.source_anchor = None
        self.target_anchor = None

        # Set up brush properties
        self.brush_radius = 12
        self.brush_circular = False
        self.brush_feathered = False    # TODO: How to make brush actually feathered?
Beispiel #2
0
class EditorView(object):
    def __init__(self, algorithm="reference", algorithm_kwargs=None):
        """This is the View that renders the main editor window."""
        if algorithm_kwargs is None:
            algorithm_kwargs = {}

        self.root = tk.Tk()
        self.root.wm_title("Streaming Gradient Domain Fusion")
        self.frame = EditorViewFrame(self.root)

        # Set up editor canvas
        self.target_canvas = EditorViewCanvas(self.frame, background="#009900",
                                              highlightthickness=0)
        self.target_canvas.bind("<Button-1>", self.handle_loadtarget)
        self.source_canvas = EditorViewCanvas(self.frame, background="#00477d",
                                              highlightthickness=0)
        self.source_canvas.bind("<Button-1>", self.handle_loadsource)
        self.frame.register_canvas_set(self.target_canvas, self.source_canvas)
        self.target_canvas.grid(row=0, column=1)
        self.source_canvas.grid(row=0, column=2)

        # Set up editor menu
        menu_items = OrderedDict()
        menu_items["File"] = [("Load target image", self.handle_loadtarget, (SUPER, "o")),
                              ("Load source image", self.handle_loadsource, (SUPER, SHIFT, "o")),
                              ("Save canvas", self.handle_save, (SUPER, "s")),
                              (),
                              ("Close", self.handle_quit, (SUPER, "w"))]
        menu_items["Edit"] = [("Undo", self.handle_unimplemented, (SUPER, "z"))]
        menu_items["Brush"] = [("Square",
                                lambda: self.set_brush_circular(False), (SUPER, "1")),
                               ("Circle",
                                lambda: self.set_brush_circular(True), (SUPER, "2")),
                               ("Feathered",
                                lambda: self.set_brush_feathered(True), (SUPER, "3")),
                               ("Not Feathered",
                                lambda: self.set_brush_feathered(False), (SUPER, "4")),
                               (),
                               ("Increase brush size", self.increase_brush_size, (CONTROL, "bracketright")),
                               ("Decrease brush size", self.decrease_brush_size, (CONTROL, "bracketleft"))]
        menu_items["Help"] = []
        self.menu = MenuBuilder(items=menu_items)
        self.menu.render(self.root)

        # Set up editor window
        self.frame.pack(fill=tk.BOTH, expand=tk.YES)
        self.root.geometry("1200x500")
        self.fusion = get_fusion_algorithm(algorithm)(**algorithm_kwargs)
        self.mask_ndarray = None
        self.source_anchor = None
        self.target_anchor = None

        # Set up brush properties
        self.brush_radius = 12
        self.brush_circular = False
        self.brush_feathered = False    # TODO: How to make brush actually feathered?

    def handle_loadtarget(self, event=None, image_path=None):
        if not image_path:
            image_path = filedialog.askopenfilename()
        if image_path:
            _log.info("Loading target image file: %s", repr(image_path))
            im = imread(image_path)
            h, w, channels = im.shape
            self.fusion.set_target_image(im)
            self.mask_ndarray = np.zeros((h, w), dtype=np.bool)
            self.target_canvas.bind("<Button-1>", self.handle_brush_start)
            self.target_canvas.bind("<B1-Motion>", self.handle_brush_motion)
            self.target_canvas.draw_numpy(self.fusion.get_fusion())

    def handle_loadsource(self, event=None, image_path=None):
        if not image_path:
            image_path = filedialog.askopenfilename()
        if image_path:
            _log.info("Loading source image file: %s", repr(image_path))
            im = imread(image_path)
            self.fusion.set_source_image(im)
            self.source_canvas.draw_numpy(im)
            self.source_canvas.bind("<Button-1>", self.handle_anchor)
            self.source_canvas.config(cursor="crosshair")

    def handle_brush_start(self, event):
        if self.target_anchor is None:
            self.target_anchor = np.array([event.y, event.x])
        if self.source_anchor is None:
            self.source_anchor = np.copy(self.target_anchor)
        self.fusion.set_anchor_points(self.source_anchor, self.target_anchor)
        self.handle_brush_motion(event)

    def handle_brush_motion(self, event):
        y_coord, x_coord = event.y, event.x
        t_height, t_width = self.mask_ndarray.shape
        if y_coord < t_height and x_coord < t_width:
            self.set_brush_stroke_in_mask(y_coord, x_coord)
            self.fusion.update_blend(self.mask_ndarray)
            self.target_canvas.draw_numpy(self.fusion.get_fusion())

    def handle_anchor(self, event):
        self.target_anchor = None
        self.source_anchor = np.array([event.y, event.x])
        self.fusion.commit_blend()
        self.mask_ndarray.fill(False)

    def handle_save(self, event=None):
        _log.info("Saving image file: %s", repr(filedialog.askopenfilename()))

    def set_brush_stroke_in_mask(self, y, x):
        # TODO: Feathered still does nothing
        height, width = self.mask_ndarray.shape
        radius = self.brush_radius
        if self.brush_circular:
            brush_y, brush_x = np.ogrid[-y:height - y, -x:width - x]
            mask = brush_x * brush_x + brush_y * brush_y <= radius * radius
            self.mask_ndarray[mask] = True
        else:
            y1, y2 = max(y - radius, 0), min(height, y + radius)
            x1, x2 = max(x - radius, 0), min(width, x + radius)
            self.mask_ndarray[y1:y2, x1:x2] = True

    def set_brush_circular(self, circle):
        self.brush_circular = circle

    def set_brush_feathered(self, feathered):
        self.brush_feathered = feathered

    def increase_brush_size(self, event=None):
        # TODO: Disable menu item if brush size is already too large
        self.brush_radius += 5

    def decrease_brush_size(self, event=None):
        # TODO: Disable menu item if brush size is already too small
        self.brush_radius -= 5

    def handle_unimplemented(self, event=None):
        _log.warn("Unimplemented event handler triggered")

    def handle_quit(self, event=None):
        self.frame.quit()

    def mainloop(self):
        return self.root.mainloop()