From 2bff95e5896bfe814c57ff892b3072bca9a13b7d Mon Sep 17 00:00:00 2001 From: YiZhou Chen <71769312+geoyee@users.noreply.github.com> Date: Tue, 13 Jul 2021 19:46:32 +0800 Subject: [PATCH] Add redo in EISeg --- contrib/EISeg/README.md | 4 +-- contrib/EISeg/eiseg/app.py | 14 ++++++++- contrib/EISeg/eiseg/controller.py | 43 ++++++++++++++++++++------ contrib/EISeg/eiseg/resource/Redo.png | Bin 0 -> 4711 bytes 4 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 contrib/EISeg/eiseg/resource/Redo.png diff --git a/contrib/EISeg/README.md b/contrib/EISeg/README.md index 4108dc0793..41334a7def 100644 --- a/contrib/EISeg/README.md +++ b/contrib/EISeg/README.md @@ -3,7 +3,7 @@ # EISeg -EISeg(Efficient Interactive Segmentation)是基于飞桨开发的一个高效智能的交互式分割标注软件. 它使用了RITM(Reviving Iterative Training with Mask Guidance for Interactive Segmentation)算法,涵盖了高精度和轻量级等不同方向的高质量交互式分割模型,方便开发者快速实现语义及实例标签的标注,降低标注成本。 另外,将EISeg获取到的标注应用到PaddleSeg提供的其他分割模型进行训练,便可得到定制化场景的高精度模型,打通分割任务从数据标注到模型训练及预测的全流程。 +EISeg(Efficient Interactive Segmentation)是基于飞桨开发的一个高效智能的交互式分割标注软件。它使用了RITM(Reviving Iterative Training with Mask Guidance for Interactive Segmentation)算法,涵盖了高精度和轻量级等不同方向的高质量交互式分割模型,方便开发者快速实现语义及实例标签的标注,降低标注成本。 另外,将EISeg获取到的标注应用到PaddleSeg提供的其他分割模型进行训练,便可得到定制化场景的高精度模型,打通分割任务从数据标注到模型训练及预测的全流程。 @@ -62,7 +62,7 @@ eiseg ### Windows exe -EISeg使用[QPT](https://github.com/GT-ZhangAcer/QPT)进行打包。可以从[百度云盘](https://pan.baidu.com/s/1XF_Fi6HK28XnPvfuVGj0bA)(提取码:82z9)下载最新EISeg。解压后双击启动程序.exe即可运行程序。程序第一次运行会初始化安装所需要的包,请稍等片刻。 +EISeg使用[QPT](https://github.com/GT-ZhangAcer/QPT)进行打包。可以从[百度云盘](https://pan.baidu.com/s/1skX0Zz6mxH8snpm7MOlzaQ)(提取码:82z9)下载最新EISeg。解压后双击启动程序.exe即可运行程序。程序第一次运行会初始化安装所需要的包,请稍等片刻。 ### 运行代码 diff --git a/contrib/EISeg/eiseg/app.py b/contrib/EISeg/eiseg/app.py index fee0039998..1f98152746 100644 --- a/contrib/EISeg/eiseg/app.py +++ b/contrib/EISeg/eiseg/app.py @@ -161,6 +161,13 @@ def menu(title, actions=None): "Undo", self.tr("撤销一次点击"), ) + redo = action( + self.tr("&重做"), + self.redoClick, + shortcuts["redo"], + "Redo", + self.tr("重做一次点击"), + ) save = action( self.tr("&保存"), self.saveLabel, @@ -253,6 +260,7 @@ def menu(title, actions=None): finish_object, clear, undo, + redo, turn_prev, turn_next, ), @@ -774,7 +782,11 @@ def undoAll(self): self.setClean() def redoClick(self): - self.toBeImplemented() + if self.image is None: + return + if not self.controller: + return + self.controller.redo_click() def canvasClick(self, x, y, isLeft): if self.controller is None: diff --git a/contrib/EISeg/eiseg/controller.py b/contrib/EISeg/eiseg/controller.py index 20ebceea28..c71847c8fa 100644 --- a/contrib/EISeg/eiseg/controller.py +++ b/contrib/EISeg/eiseg/controller.py @@ -17,6 +17,8 @@ def __init__(self, net, predictor_params, update_image_callback, prob_thresh=0.5 self.clicker = clicker.Clicker() self.states = [] self.probs_history = [] + self.undo_states = [] + self.undo_probs_history = [] self.curr_label_number = 0 self._result_mask = None self.label_list = None # 存标签编号和颜色的对照 @@ -70,20 +72,30 @@ def add_click(self, x, y, is_positive): s = self.image.shape if x < 0 or y < 0 or x >= s[1] or y >= s[0]: return False - self.states.append( - { + + if len(self.states) == 0: # 保存最初状态 + self.states.append({ "clicker": self.clicker.get_state(), "predictor": self.predictor.get_states(), - } - ) + }) click = clicker.Click(is_positive=is_positive, coords=(y, x)) self.clicker.add_click(click) + start = time.time() + print(self.predictor) pred = self.predictor.get_prediction(self.clicker, prev_mask=self._init_mask) if self._init_mask is not None and len(self.clicker) == 1: pred = self.predictor.get_prediction( self.clicker, prev_mask=self._init_mask ) + end = time.time() + print("cost time", end - start) + + # 保存最新状态 + self.states.append({ + "clicker": self.clicker.get_state(), + "predictor": self.predictor.get_states(), + }) if self.probs_history: self.probs_history.append((self.probs_history[-1][0], pred)) @@ -97,17 +109,28 @@ def set_label(self, label): def undo_click(self): """undo一步点击""" - if not self.states: # 如果还没点 + if len(self.states) == 1: # 如果还没点 return - - prev_state = self.states.pop() - self.clicker.set_state(prev_state["clicker"]) - self.predictor.set_states(prev_state["predictor"]) - self.probs_history.pop() + self.undo_states.append(self.states.pop()) + self.clicker.set_state(self.states[-1]["clicker"]) + self.predictor.set_states(self.states[-1]["predictor"]) + self.undo_probs_history.append(self.probs_history.pop()) if not self.probs_history: self.reset_init_mask() self.update_image_callback() + def redo_click(self): + """redo一步点击""" + if not self.undo_states: # 如果还没撤销过 + return + if len(self.undo_probs_history) >= 1: + next_state = self.undo_states.pop() + self.states.append(next_state) + self.clicker.set_state(next_state["clicker"]) + self.predictor.set_states(next_state["predictor"]) + self.probs_history.append(self.undo_probs_history.pop()) + self.update_image_callback() + def partially_finish_object(self): """部分完成 保存一个mask的状态,这个状态里不存点,看起来比较 diff --git a/contrib/EISeg/eiseg/resource/Redo.png b/contrib/EISeg/eiseg/resource/Redo.png new file mode 100644 index 0000000000000000000000000000000000000000..5bf985547c5f177d4b88aed46074598704f9e199 GIT binary patch literal 4711 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