def load_images(self):
        self.left_pic = cv2.imread(self.left_file, 1)
        self.right_pic = cv2.imread(self.right_file, 1)

        shape = [
            max(v1, v2) for v1, v2 in zip(self.left_pic.shape[:2],
                                          self.right_pic.shape[:2])
        ]

        self.left_img = self.left_axe.imshow(self.left_pic[::-1, :, ::-1],
                                             origin="lower")
        self.left_axe.axis("off")
        self.left_mask = ImageMaskDrawer(self.left_axe,
                                         self.left_img,
                                         mask_shape=shape)

        self.right_img = self.right_axe.imshow(self.right_pic[::-1, :, ::-1],
                                               origin="lower")
        self.right_axe.axis("off")
        self.right_mask = ImageMaskDrawer(self.right_axe,
                                          self.right_img,
                                          mask_shape=shape)

        self.left_mask.on_trait_change(self.mask_changed, "drawed")
        self.right_mask.on_trait_change(self.mask_changed, "drawed")
        self.figure.canvas.draw_idle()
Пример #2
0
 def init_draw(self):
     h, w = self.img.shape[:2]
     if self.mask_artist is not None:
         self.mask_artist.remove()
     self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(h, w),
                                        canmove=False, size=10)
     self.mask_artist.on_trait_change(self.update_markers, "drawed")
     self.markers = np.zeros((h, w), dtype=np.int32)
     self.result = np.zeros((h, w), dtype=np.int32)
Пример #3
0
class WatershedDemo(ImageProcessDemo):
    TITLE = "Watershed Demo"
    DEFAULT_IMAGE = "fruits.jpg"
    YAXIS_DIRECTION = "up"

    current_label = Enum(list(range(1, 10)))

    def __init__(self, **kw):
        super(WatershedDemo, self).__init__(**kw)
        self.figure.canvas_events = [("button_press_event",
                                      self.on_button_pressed)]
        self.result_artist = self.axe.imshow(np.zeros((10, 10, 3), np.uint8),
                                             alpha=0.3)
        self.mask_artist = None
        self.markers = None

    def control_panel(self):
        return VGroup(Item("current_label", label="当前标签"))

    def on_button_pressed(self, event):
        if event.inaxes is self.axe and event.button == 3:
            if self.current_label < 9:
                self.current_label += 1
            else:
                self.current_label = 1

    def init_draw(self):
        h, w = self.img.shape[:2]
        if self.mask_artist is not None:
            self.mask_artist.remove()
        self.mask_artist = ImageMaskDrawer(self.axe,
                                           mask_shape=(h, w),
                                           canmove=False,
                                           size=10)
        self.mask_artist.on_trait_change(self.update_markers, "drawed")
        self.markers = np.zeros((h, w), dtype=np.int32)
        self.result = np.zeros((h, w), dtype=np.int32)

    def update_markers(self):
        mask = self.mask_artist.get_mask_array().astype(bool)
        y, x = np.where(mask)
        self.markers[y, x] = self.current_label
        self.mask_artist.clear_mask()
        self.draw()

    def draw(self):
        if self.markers is not None:
            if self.img.shape[:2] != self.markers.shape:
                self.init_draw()

            self.result[:] = self.markers
            cv2.watershed(self.img, self.result)
            img = MARKER_COLORS[self.result]
            self.draw_image(img, self.result_artist, draw=False)
            self.draw_image(self.img)
Пример #4
0
class WatershedDemo(ImageProcessDemo):
    TITLE = u"Watershed Demo"
    DEFAULT_IMAGE = u"fruits.jpg"
    YAXIS_DIRECTION = "up"

    current_label = Enum(range(1, 10))

    def __init__(self, **kw):
        super(WatershedDemo, self).__init__(**kw)
        self.figure.canvas_events = [
            ("button_press_event", self.on_button_pressed)
        ]
        self.result_artist = self.axe.imshow(np.zeros((10, 10, 3), np.uint8), alpha=0.3)
        self.mask_artist = None
        self.markers = None

    def control_panel(self):
        return VGroup(
            Item("current_label", label=u"当前标签")
        )

    def on_button_pressed(self, event):
        if event.inaxes is self.axe and event.button == 3:
            if self.current_label < 9:
                self.current_label += 1
            else:
                self.current_label = 1

    def init_draw(self):
        h, w = self.img.shape[:2]
        if self.mask_artist is not None:
            self.mask_artist.remove()
        self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(h, w),
                                           canmove=False, size=10)
        self.mask_artist.on_trait_change(self.update_markers, "drawed")
        self.markers = np.zeros((h, w), dtype=np.int32)
        self.result = np.zeros((h, w), dtype=np.int32)

    def update_markers(self):
        mask = self.mask_artist.get_mask_array().astype(bool)
        y, x = np.where(mask)
        self.markers[y, x] = self.current_label
        self.mask_artist.clear_mask()
        self.draw()

    def draw(self):
        if self.markers is not None:
            if self.img.shape[:2] != self.markers.shape:
                self.init_draw()

            self.result[:] = self.markers
            cv2.watershed(self.img, self.result)
            img = MARKER_COLORS[self.result]
            self.draw_image(img, self.result_artist, draw=False)
            self.draw_image(self.img)
Пример #5
0
    def load_images(self):
        self.left_pic = cv2.imread(path.join(FOLDER, "vinci_src.png"), 1)
        self.right_pic = cv2.imread(path.join(FOLDER, "vinci_target.png"), 1)
        
        shape = [max(v1, v2) for v1, v2 in 
                    zip(self.left_pic.shape[:2], self.right_pic.shape[:2])]

        self.left_img = self.left_axe.imshow(self.left_pic[::-1, :, ::-1], origin="upper")
        self.left_axe.axis("off")
        self.left_mask = ImageMaskDrawer(self.left_axe, self.left_img, mask_shape=shape)
        
        self.right_img = self.right_axe.imshow(self.right_pic[::-1, :, ::-1], origin="upper")
        self.right_axe.axis("off")
        self.right_mask = ImageMaskDrawer(self.right_axe, self.right_img, mask_shape=shape)

        self.left_mask.on_trait_change(self.mask_changed, "drawed")
        self.right_mask.on_trait_change(self.mask_changed, "drawed")
Пример #6
0
    def load_images(self):
        self.left_pic = cv2.imread(self.left_file, 1)
        self.right_pic = cv2.imread(self.right_file, 1)

        shape = [max(v1, v2) for v1, v2 in
                 zip(self.left_pic.shape[:2], self.right_pic.shape[:2])]

        self.left_img = self.left_axe.imshow(self.left_pic[::-1, :, ::-1], origin="lower")
        self.left_axe.axis("off")
        self.left_mask = ImageMaskDrawer(self.left_axe, self.left_img, mask_shape=shape)

        self.right_img = self.right_axe.imshow(self.right_pic[::-1, :, ::-1], origin="lower")
        self.right_axe.axis("off")
        self.right_mask = ImageMaskDrawer(self.right_axe, self.right_img, mask_shape=shape)

        self.left_mask.on_trait_change(self.mask_changed, "drawed")
        self.right_mask.on_trait_change(self.mask_changed, "drawed")
        self.figure.canvas.draw_idle()
Пример #7
0
class FFT2DDemo(ImageProcessDemo):
    YAXIS_DIRECTION = "up"
    TITLE = "FFT2D Demo"
    DEFAULT_IMAGE = "lena.jpg"

    mask_artist = Instance(ImageMaskDrawer)
    reset = Button(u"Reset")

    def __init__(self, **kw):
        super(FFT2DDemo, self).__init__(**kw)
        self.mask_artist = None

    def control_panel(self):
        return VGroup(
            "reset",
            show_labels=False,
        )

    def init_draw(self):
        self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(512, 512),
                                           canmove=False, size=15)
        self.mask_artist.on_trait_change(self.draw, "mask_updated")

    def _reset_fired(self):
        self.mask_artist.clear_mask()
        self.mask_artist.update()
        self.draw()

    def _img_changed(self):
        w, h = self.img.shape[:2]
        if w >= 512 and h >= 512:
            self.img_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)[:512, :512].copy()
            self.img_freq = fft.fft2(self.img_gray)
            self.img_mag = fft.fftshift(np.log10(np.abs(self.img_freq)))
            self.img_show = np.hstack((self.img[:512, :512, :], self.img[:512, :512, :]))
            self.img_show[:512, 512:, :] = self.img_gray[:512, :512, None]

            img_uint8 = normalize_gray_image(self.img_mag)
            self.img_show[:512, :512, :] = img_uint8[:, :, None]

    def draw(self):
        if self.mask_artist is None:
            self.draw_image(self.img_show)
            return

        mask = self.mask_artist.get_mask_array().astype(np.bool)

        if np.any(mask):
            y, x = np.where(mask)
            mask[512-y+1, 512-x+1] = True
            self.mask_artist.array[:, :, -1] = mask * 255
            filtered_img = fft.ifft2(self.img_freq * fft.fftshift(mask)).real
            filtered_img = normalize_gray_image(filtered_img)
            self.img_show[:512, 512:, :] = filtered_img[:, :, None]
        else:
            self.img_show[:512, 512:, :] = self.img_gray[:, :, None]

        self.draw_image(self.img_show)
Пример #8
0
 def init_draw(self):
     self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(512, 512),
                                        canmove=False, size=15)
     self.connect_dirty("mask_artist.mask_updated")
Пример #9
0
class FFT2DDemo(ImageProcessDemo):
    YAXIS_DIRECTION = "up"
    TITLE = "FFT2D Demo"
    DEFAULT_IMAGE = "lena.jpg"

    mask_artist = Instance(ImageMaskDrawer)
    reset = Button(u"Reset")

    def __init__(self, **kw):
        super(FFT2DDemo, self).__init__(**kw)
        self.mask_artist = None
        self.figure.canvas_events = [
            ("button_press_event", self.on_button_pressed)
        ]

    def control_panel(self):
        return VGroup(
            "reset",
            show_labels=False,
        )

    def init_draw(self):
        self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(512, 512),
                                           canmove=False, size=15)
        self.connect_dirty("mask_artist.mask_updated")

    def on_button_pressed(self, event):
        if event.inaxes is self.axe:
            if event.button == 3:
                self._reset_fired()

    def _reset_fired(self):
        self.mask_artist.clear_mask()
        self.mask_artist.update()
        self.draw()

    def _img_changed(self):
        img = cv2.resize(self.img, (FFT_SIZE, FFT_SIZE))
        w, h = img.shape[:2]

        self.img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)[:FFT_SIZE, :FFT_SIZE].copy()
        self.img_freq = fft.fft2(self.img_gray)
        self.img_mag = fft.fftshift(np.log10(np.abs(self.img_freq)))
        self.img_show = np.hstack((img[:FFT_SIZE, :FFT_SIZE, :], img[:FFT_SIZE, :FFT_SIZE, :]))
        self.img_show[:FFT_SIZE, FFT_SIZE:, :] = self.img_gray[:FFT_SIZE, :FFT_SIZE, None]

        img_uint8 = normalize_gray_image(self.img_mag)
        self.img_show[:FFT_SIZE, :FFT_SIZE, :] = img_uint8[:, :, None]

    def draw(self):
        if self.mask_artist is None:
            self.draw_image(self.img_show)
            return

        mask = self.mask_artist.get_mask_array().astype(np.bool)

        if np.any(mask):
            y, x = np.where(mask)
            m = (y > 0) & (x > 0)
            x, y = x[m], y[m]
            mask[FFT_SIZE - y, FFT_SIZE - x] = True
            self.mask_artist.array[:, :, -1] = mask * 255
            filtered_img = fft.ifft2(self.img_freq * fft.fftshift(mask)).real
            filtered_img = normalize_gray_image(filtered_img)
            self.img_show[:FFT_SIZE, FFT_SIZE:, :] = filtered_img[:, :, None]
        else:
            self.img_show[:FFT_SIZE, FFT_SIZE:, :] = self.img_gray[:, :, None]

        self.draw_image(self.img_show)
Пример #10
0
 def init_draw(self):
     self.mask_artist = ImageMaskDrawer(self.axe,
                                        mask_shape=(512, 512),
                                        canmove=False,
                                        size=15)
     self.connect_dirty("mask_artist.mask_updated")
Пример #11
0
class FFT2DDemo(ImageProcessDemo):
    YAXIS_DIRECTION = "up"
    TITLE = "FFT2D Demo"
    DEFAULT_IMAGE = "lena.jpg"

    mask_artist = Instance(ImageMaskDrawer)
    reset = Button(u"Reset")

    def __init__(self, **kw):
        super(FFT2DDemo, self).__init__(**kw)
        self.mask_artist = None
        self.figure.canvas_events = [("button_press_event",
                                      self.on_button_pressed)]

    def control_panel(self):
        return VGroup(
            "reset",
            show_labels=False,
        )

    def init_draw(self):
        self.mask_artist = ImageMaskDrawer(self.axe,
                                           mask_shape=(512, 512),
                                           canmove=False,
                                           size=15)
        self.connect_dirty("mask_artist.mask_updated")

    def on_button_pressed(self, event):
        if event.inaxes is self.axe:
            if event.button == 3:
                self._reset_fired()

    def _reset_fired(self):
        self.mask_artist.clear_mask()
        self.mask_artist.update()
        self.draw()

    def _img_changed(self):
        img = cv2.resize(self.img, (FFT_SIZE, FFT_SIZE))
        w, h = img.shape[:2]

        self.img_gray = cv2.cvtColor(
            img, cv2.COLOR_BGR2GRAY)[:FFT_SIZE, :FFT_SIZE].copy()
        self.img_freq = fft.fft2(self.img_gray)
        self.img_mag = fft.fftshift(np.log10(np.abs(self.img_freq)))
        self.img_show = np.hstack(
            (img[:FFT_SIZE, :FFT_SIZE, :], img[:FFT_SIZE, :FFT_SIZE, :]))
        self.img_show[:FFT_SIZE,
                      FFT_SIZE:, :] = self.img_gray[:FFT_SIZE, :FFT_SIZE, None]

        img_uint8 = normalize_gray_image(self.img_mag)
        self.img_show[:FFT_SIZE, :FFT_SIZE, :] = img_uint8[:, :, None]

    def draw(self):
        if self.mask_artist is None:
            self.draw_image(self.img_show)
            return

        mask = self.mask_artist.get_mask_array().astype(np.bool)

        if np.any(mask):
            y, x = np.where(mask)
            m = (y > 0) & (x > 0)
            x, y = x[m], y[m]
            mask[FFT_SIZE - y, FFT_SIZE - x] = True
            self.mask_artist.array[:, :, -1] = mask * 255
            filtered_img = fft.ifft2(self.img_freq * fft.fftshift(mask)).real
            filtered_img = normalize_gray_image(filtered_img)
            self.img_show[:FFT_SIZE, FFT_SIZE:, :] = filtered_img[:, :, None]
        else:
            self.img_show[:FFT_SIZE, FFT_SIZE:, :] = self.img_gray[:, :, None]

        self.draw_image(self.img_show)
Пример #12
0
 def init_draw(self):
     self.mask_artist = ImageMaskDrawer(self.axe,
                                        self.img,
                                        canmove=False,
                                        size=15)
     self.mask_artist.on_trait_change(self.draw, "drawed")
Пример #13
0
 def init_draw(self):
     self.mask_artist = ImageMaskDrawer(self.axe, self.img,
                                        canmove=False, size=15)
     self.mask_artist.on_trait_change(self.draw, "drawed")
Пример #14
0
class InPaintDemo(ImageProcessDemo):
    YAXIS_DIRECTION = "up"
    TITLE = u"Inpaint Demo"
    DEFAULT_IMAGE = "stuff.jpg"

    mask_artist = Instance(ImageMaskDrawer)
    r = Range(2.0, 20.0, 10.0)  # inpaint的半径参数
    method = Enum("INPAINT_NS", "INPAINT_TELEA")  # inpaint的算法
    show_mask = Bool(False)  # 是否显示选区
    clear_mask = Button(u"清除选区")
    apply = Button(u"保存结果")

    def control_panel(self):
        return VGroup(
            Item("r", label=u"inpaint半径"),
            Item("method", label=u"inpaint算法"),
            Item("show_mask", label=u"显示选区"),
            Item("clear_mask", show_label=False),
            Item("apply", show_label=False),
        )

    def __init__(self, **kw):
        super(InPaintDemo, self).__init__(**kw)
        self.connect_dirty("r, method")

    def init_draw(self):
        self.mask_artist = ImageMaskDrawer(self.axe, self.img,
                                           canmove=False, size=15)
        self.mask_artist.on_trait_change(self.draw, "drawed")

    def draw(self):
        if self.mask_artist is None:
            self.draw_image(self.img)
            return
        mask = self.mask_artist.get_mask_array()
        if self.img.shape[:2] == mask.shape:
            img2 = cv2.inpaint(self.img, mask, self.r, getattr(cv2, self.method))
            self.img2 = img2
            self.show_mask = False
            self.mask_artist.hide_mask()
            self.draw_image(img2)
        else:
            self.draw_image(self.img)

    def _img_changed(self):
        if self.mask_artist is not None:
            self.mask_artist.create_mask(img=self.img)

    def _show_mask_changed(self):
        if self.show_mask:
            self.mask_artist.show_mask()
        else:
            self.mask_artist.hide_mask()
        self.figure.canvas.draw()

    def _clear_mask_fired(self):
        self.mask_artist.clear_mask()
        self.draw()

    def _apply_fired(self):
        if hasattr(self, "img2"):
            self.img[:] = self.img2[:]
        self.clear_mask = True
Пример #15
0
 def init_draw(self):
     self.mask_artist = ImageMaskDrawer(self.axe, mask_shape=(512, 512),
                                        canmove=False, size=15)
     self.mask_artist.on_trait_change(self.draw, "mask_updated")
Пример #16
0
class PossionDemo(HasTraits):
    left_mask = Instance(ImageMaskDrawer)
    right_mask = Instance(ImageMaskDrawer)
    left_file = File
    right_file = File
    figure = Instance(Figure, ())
    load_button = Button(u"Load")
    clear_button = Button(u"Clear")
    mix_button = Button(u"Mix")

    view = View(
        Item("left_file"),
        Item("right_file"),
        VGroup(
            HGroup(
                "load_button", "clear_button", "mix_button",
                show_labels = False
            ),
            Group(
                Item("figure", editor=MPLFigureEditor(toolbar=False)),
                show_labels = False,
                orientation = 'horizontal'
            )
        ),
        width = 800,
        height = 600,
        resizable = True)
        
    def __init__(self, **kw):
        super(PossionDemo, self).__init__(**kw)
        self.left_axe = self.figure.add_subplot(121)
        self.right_axe = self.figure.add_subplot(122)
        
    def load_images(self):
        self.left_pic = cv2.imread(path.join(FOLDER, "vinci_src.png"), 1)
        self.right_pic = cv2.imread(path.join(FOLDER, "vinci_target.png"), 1)
        
        shape = [max(v1, v2) for v1, v2 in 
                    zip(self.left_pic.shape[:2], self.right_pic.shape[:2])]

        self.left_img = self.left_axe.imshow(self.left_pic[::-1, :, ::-1], origin="upper")
        self.left_axe.axis("off")
        self.left_mask = ImageMaskDrawer(self.left_axe, self.left_img, mask_shape=shape)
        
        self.right_img = self.right_axe.imshow(self.right_pic[::-1, :, ::-1], origin="upper")
        self.right_axe.axis("off")
        self.right_mask = ImageMaskDrawer(self.right_axe, self.right_img, mask_shape=shape)

        self.left_mask.on_trait_change(self.mask_changed, "drawed")
        self.right_mask.on_trait_change(self.mask_changed, "drawed")
        
    def mask_changed(self, obj, name, new):
        if obj is self.left_mask:
            src, target = self.left_mask, self.right_mask
        else:
            src, target = self.right_mask, self.left_mask
        target.array.fill(0)
        target.array[:, :] = src.array[:, :]
        target.update()
        self.figure.canvas.draw()
        
    def _mix_button_fired(self):
        lh, lw, _ = self.left_pic.shape
        rh, rw, _ = self.right_pic.shape
        
        left_mask = self.left_mask.array[-lh:, :lw, -1]
        
        dx, dy = self.right_mask.get_mask_offset()
        result = possion_mix(self.left_pic, self.right_pic, left_mask, (dx, rh-lh-dy))

        self.right_img.set_data(result[::-1, :, ::-1])
        self.right_mask.mask_img.set_visible(False)
        self.figure.canvas.draw()
        
    def _clear_button_fired(self):
        self.left_mask.array.fill(0)
        self.right_mask.array.fill(0)
        self.left_mask.update()
        self.right_mask.update()
        self.figure.canvas.draw()
class PossionDemo(HasTraits):
    left_mask = Instance(ImageMaskDrawer)
    right_mask = Instance(ImageMaskDrawer)
    left_file = File(path.join(FOLDER, "vinci_src.png"))
    right_file = File(path.join(FOLDER, "vinci_target.png"))
    figure = Instance(Figure, ())
    load_button = Button(u"Load")
    clear_button = Button(u"Clear")
    mix_button = Button(u"Mix")

    view = View(Item("left_file"),
                Item("right_file"),
                VGroup(
                    HGroup("load_button",
                           "clear_button",
                           "mix_button",
                           show_labels=False),
                    Group(Item("figure",
                               editor=MPLFigureEditor(toolbar=False)),
                          show_labels=False,
                          orientation='horizontal')),
                width=800,
                height=600,
                resizable=True,
                title="Possion Demo")

    def __init__(self, **kw):
        super(PossionDemo, self).__init__(**kw)
        self.left_axe = self.figure.add_subplot(121)
        self.right_axe = self.figure.add_subplot(122)

    def load_images(self):
        self.left_pic = cv2.imread(self.left_file, 1)
        self.right_pic = cv2.imread(self.right_file, 1)

        shape = [
            max(v1, v2) for v1, v2 in zip(self.left_pic.shape[:2],
                                          self.right_pic.shape[:2])
        ]

        self.left_img = self.left_axe.imshow(self.left_pic[::-1, :, ::-1],
                                             origin="lower")
        self.left_axe.axis("off")
        self.left_mask = ImageMaskDrawer(self.left_axe,
                                         self.left_img,
                                         mask_shape=shape)

        self.right_img = self.right_axe.imshow(self.right_pic[::-1, :, ::-1],
                                               origin="lower")
        self.right_axe.axis("off")
        self.right_mask = ImageMaskDrawer(self.right_axe,
                                          self.right_img,
                                          mask_shape=shape)

        self.left_mask.on_trait_change(self.mask_changed, "drawed")
        self.right_mask.on_trait_change(self.mask_changed, "drawed")
        self.figure.canvas.draw_idle()

    def mask_changed(self, obj, name, new):
        if obj is self.left_mask:
            src, target = self.left_mask, self.right_mask
        else:
            src, target = self.right_mask, self.left_mask
        target.array.fill(0)
        target.array[:, :] = src.array[:, :]
        target.update()
        self.figure.canvas.draw()

    def _load_button_fired(self):
        self.load_images()

    def _mix_button_fired(self):
        lh, lw, _ = self.left_pic.shape
        rh, rw, _ = self.right_pic.shape

        left_mask = self.left_mask.array[-lh:, :lw, -1]
        if np.all(left_mask == 0):
            return

        dx, dy = self.right_mask.get_mask_offset()
        result = possion_mix(self.left_pic, self.right_pic, left_mask,
                             (dx, rh - lh - dy))

        self.right_img.set_data(result[::-1, :, ::-1])
        self.right_mask.mask_img.set_visible(False)
        self.figure.canvas.draw()

    def _clear_button_fired(self):
        self.left_mask.array.fill(0)
        self.right_mask.array.fill(0)
        self.left_mask.update()
        self.right_mask.update()
        self.figure.canvas.draw()
Пример #18
0
class InPaintDemo(ImageProcessDemo):
    YAXIS_DIRECTION = "up"
    TITLE = u"Inpaint Demo"
    DEFAULT_IMAGE = "stuff.jpg"

    mask_artist = Instance(ImageMaskDrawer)
    r = Range(2.0, 20.0, 10.0)  # inpaint的半径参数
    method = Enum("INPAINT_NS", "INPAINT_TELEA")  # inpaint的算法
    show_mask = Bool(False)  # 是否显示选区
    clear_mask = Button(u"清除选区")
    apply = Button(u"保存结果")

    def control_panel(self):
        return VGroup(
            Item("r", label=u"inpaint半径"),
            Item("method", label=u"inpaint算法"),
            Item("show_mask", label=u"显示选区"),
            Item("clear_mask", show_label=False),
            Item("apply", show_label=False),
        )

    def __init__(self, **kw):
        super(InPaintDemo, self).__init__(**kw)
        self.connect_dirty("r, method")

    def init_draw(self):
        self.mask_artist = ImageMaskDrawer(self.axe,
                                           self.img,
                                           canmove=False,
                                           size=15)
        self.mask_artist.on_trait_change(self.draw, "drawed")

    def draw(self):
        if self.mask_artist is None:
            self.draw_image(self.img)
            return
        mask = self.mask_artist.get_mask_array()
        if self.img.shape[:2] == mask.shape:
            img2 = cv2.inpaint(self.img, mask, self.r,
                               getattr(cv2, self.method))
            self.img2 = img2
            self.show_mask = False
            self.mask_artist.hide_mask()
            self.draw_image(img2)
        else:
            self.draw_image(self.img)

    def _img_changed(self):
        if self.mask_artist is not None:
            self.mask_artist.create_mask(img=self.img)

    def _show_mask_changed(self):
        if self.show_mask:
            self.mask_artist.show_mask()
        else:
            self.mask_artist.hide_mask()
        self.figure.canvas.draw()

    def _clear_mask_fired(self):
        self.mask_artist.clear_mask()
        self.draw()

    def _apply_fired(self):
        if hasattr(self, "img2"):
            self.img[:] = self.img2[:]
        self.clear_mask = True