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 0000000000..5bf985547c Binary files /dev/null and b/contrib/EISeg/eiseg/resource/Redo.png differ