Repository: PaddlePaddle/PaddleSeg

Issue:
CPU模式使用eiseg标注图片，点击完成宫格出现错误闪退
### 问题确认 Search before asking

- [x] 我已经搜索过问题，但是没有找到解答。I have searched the question and found no related answer.


### 请提出你的问题 Please ask your question

用的static_hrnet18s_ocr48_cocolvis模型，最新cpu版本的paddlepaddle，和最新版本的paddleseg
标注完成后，点击完成宫格出现错误闪退
![微信截图_20230104233723](https://user-images.githubusercontent.com/61500782/210591801-ab9bd199-273f-4511-b067-003318b3d64a.png)
第二次打开eiseg读取文件夹图片后
![微信截图_20230104233737](https://user-images.githubusercontent.com/61500782/210591929-e9946ac9-84ae-43d6-83c9-741040723220.png)



Discussion:

Resolving patch:
diff --git a/EISeg/eiseg/__init__.py b/EISeg/eiseg/__init__.py
--- a/EISeg/eiseg/__init__.py
+++ b/EISeg/eiseg/__init__.py
@@ -22,7 +22,7 @@
 import cv2
 
 __APPNAME__ = "EISeg"
-__VERSION__ = "1.1.0"
+__VERSION__ = "1.1.2"
 
 pjpath = osp.dirname(osp.realpath(__file__))
 sys.path.append(pjpath)
diff --git a/EISeg/eiseg/app.py b/EISeg/eiseg/app.py
--- a/EISeg/eiseg/app.py
+++ b/EISeg/eiseg/app.py
@@ -104,6 +104,7 @@ def __init__(self, parent=None):
         self.video = InferenceCore()
         self.video_images = None
         self.video_masks = None
+        self.video_first = None
 
         self.det = DetInfer()
 
@@ -1264,14 +1265,15 @@ def labelFuzzyMatching(self):
             self.focusToLable(lab.idx)
 
     # 多边形标注
-    def createPoly(self, curr_polygon, color):
+    def createPoly(self, curr_polygon, color, label_idx=None):
         if curr_polygon is None:
             return
         for points in curr_polygon:
             if len(points) < 3:
                 continue
+            l_idx = self.currLabelIdx if label_idx is None else label_idx
             poly = PolygonAnnotation(
-                self.controller.labelList[self.currLabelIdx].idx,
+                self.controller.labelList[l_idx].idx,
                 self.controller.image.shape,
                 self.delPolygon,
                 self.setDirty,
@@ -1328,7 +1330,19 @@ def getMask(self):
                 if poly.labelIndex == idx:
                     pts = np.int32([np.array(poly.scnenePoints)])
                     cv2.fillPoly(pesudo, pts=pts, color=idx)
-        return pesudo
+        return pesudo.astype("uint8")
+
+    def createPolygonFromMask(self, mask):
+        m_shape = mask.shape
+        for i_clas in np.unique(mask):
+            if i_clas == 0:
+                continue
+            tmp_mask = (mask == i_clas).astype("uint8") * 255
+            curr_polygon = util.get_polygon(
+                tmp_mask, img_size=m_shape,
+                building=self.boundaryRegular.isChecked())
+            color = self.controller.labelList[i_clas - 1].color
+            self.createPoly(curr_polygon, color, i_clas - 1)
 
     def openRecentImage(self, file_path):
         self.queueEvent(partial(self.loadImage, file_path))
@@ -1461,6 +1475,7 @@ def loadImage(self, path):
         # 2. 判断图像类型，打开
         # TODO: 加用户指定类型的功能
         image = None
+        self.video_first = None
 
         # 直接if会报错，因为打开遥感图像后多波段不存在，现在把遥感图像的单独抽出来了
         # 自然图像
@@ -1576,6 +1591,7 @@ def loadImage(self, path):
             self.sldTime.setMaximum(self.video.num_frames - 1)
             image = self.video_images[self.video.cursur]
             self.sldTime.setProperty("value", 0)
+            self.video_first = True
             # 清空3d显示
             if self.TDDock.isVisible():
                 self.vtkWidget.init()
@@ -1590,7 +1606,6 @@ def loadImage(self, path):
         self.image = image
         self.controller.setImage(image, self.type_seg)
         self.updateImage(True)
-
         # 2. 加载标签
         self.load_label_success = self.loadLabel(path)
         self.addRecentFile(path)
@@ -1750,17 +1765,23 @@ def imageListClicked(self):
         self.turnImg(delta, True)
 
     def finishObject(self):
-        if not self.controller or self.image is None:
+        if self.image is None:
             return
-        current_mask, curr_polygon = self.controller.finishObject(
-            building=self.boundaryRegular.isChecked())
-        if curr_polygon is not None:
+        if self.controller is not None:
+            current_mask, curr_polygon = self.controller.finishObject(
+                building=self.boundaryRegular.isChecked())
+            if curr_polygon is not None:
+                self.updateImage()
+                if current_mask is not None:
+                    # current_mask = current_mask.astype(np.uint8) * 255
+                    # polygon = util.get_polygon(current_mask)
+                    color = self.controller.labelList[self.currLabelIdx].color
+                    self.createPoly(curr_polygon, color)
+        if self.video_first is False:
             self.updateImage()
-            if current_mask is not None:
-                # current_mask = current_mask.astype(np.uint8) * 255
-                # polygon = util.get_polygon(current_mask)
-                color = self.controller.labelList[self.currLabelIdx].color
-                self.createPoly(curr_polygon, color)
+            current_mask = self.getVideoMask()
+            if current_mask is not None and len(self.scene.polygon_items) == 0:
+                self.createPolygonFromMask(current_mask)
         # 状态改变
         if self.status == self.EDITING:
             self.status = self.ANNING
@@ -1770,10 +1791,6 @@ def finishObject(self):
             self.status = self.EDITING
             for p in self.scene.polygon_items:
                 p.setAnning(isAnning=False)
-        current_mask = self.getMask()
-        if self.video_images is not None:
-            if current_mask.max() != 0:
-                self.video_masks[self.video.cursur] = current_mask
 
     def completeLastMask(self):
         # 返回最后一个标签是否完成，false就是还有带点的
@@ -1954,13 +1971,16 @@ def exportLabel(self, saveAs=False, savePath=None, lab_input=None):
             if self.save_status["pseudo_color"]:
                 pseudoPath, ext = osp.splitext(savePath)
                 pseudoPath = pseudoPath + "_pseudo" + ext
-                pseudo = np.zeros([s[0], s[1], 3], dtype="uint8")
+                # color
+                bin_colormap = np.zeros((256, 3))
+                for idx, lab in enumerate(self.controller.labelList):
+                    bin_colormap[idx + 1, :] = lab.color
+                palette = bin_colormap.astype(np.uint8)
                 # mask = self.controller.result_mask
-                mask = mask_output
-                # print(pseudo.shape, mask.shape)
-                for lab in self.controller.labelList:
-                    pseudo[mask == lab.idx, :] = lab.color[::-1]
-                cv2.imencode(ext, pseudo)[1].tofile(pseudoPath)
+                mask = mask_output.astype(np.uint8)
+                visualimg = Image.fromarray(mask, "P")
+                visualimg.putpalette(palette)
+                visualimg.save(pseudoPath, format='PNG')
 
             # 4.3 保存前景抠图
             if self.save_status["cutout"]:
@@ -2913,6 +2933,8 @@ def tframeChanged(self):
     def sframeChanged(self):
         if self.video_images is None:
             return
+        if len(self.scene.polygon_items) > 0:
+            self.video_masks[self.video.cursur] = self.getMask()
         self.textTime.setText(str(self.sldTime.value()))
         self.video.cursur = int(self.textTime.text())
         self.controller.setImage(self.video_images[self.video.cursur])
@@ -2923,18 +2945,18 @@ def sframeChanged(self):
     def turnPreFrame(self):
         if self.video_images is None:
             return
-        self.video.cursur -= 1
-        if self.video.cursur < 0:
-            self.video.cursur = self.video.num_frames - 1
-        self.sldTime.setProperty("value", self.video.cursur)
+        v_cursur = self.video.cursur - 1
+        if v_cursur < 0:
+            v_cursur = self.video.num_frames - 1
+        self.sldTime.setProperty("value", v_cursur)
 
     def turnNextFrame(self):
         if self.video_images is None:
             return
-        self.video.cursur += 1
-        if self.video.cursur > self.video.num_frames - 1:
-            self.video.cursur = 0
-        self.sldTime.setProperty("value", self.video.cursur)
+        v_cursur = self.video.cursur + 1
+        if v_cursur > self.video.num_frames - 1:
+            v_cursur = 0
+        self.sldTime.setProperty("value", v_cursur)
 
     def show_current_frame(self):
         self.viz = overlay_davis(self.video_images[self.video.cursur],
@@ -2958,20 +2980,20 @@ def on_play(self):
             return
         if self.timer.isActive():
             self.timer.stop()
+            self.image = self.video_images[self.video.cursur]
             self.videoPlay.setText(self.tr("播放"))
             self.videoPlay.setIcon(
                 QtGui.QIcon(osp.join(pjpath, "resource/Play.png")))
         else:
-            # self.delAllPolygon()
             self.timer.start(1000 // self.ratio)
             self.videoPlay.setText(self.tr("暂停"))
             self.videoPlay.setIcon(
                 QtGui.QIcon(osp.join(pjpath, "resource/Stop.png")))
 
     def getVideoMask(self):
-        if self.video_masks is not None:
+        try:
             return self.video_masks[self.video.cursur]
-        else:
+        except (TypeError, KeyError):
             return None
 
     def on_propgation(self):
@@ -3011,6 +3033,7 @@ def on_propgation(self):
         end = time.time()
         print("propagation time cost", end - start)
         self.statusbar.showMessage(self.tr("传播完成!"), 5000)
+        self.video_first = False
         # 传播进度条重置
         self.proPropagete.setValue(0)
         self.proPropagete.setFormat('0%')


Test patch: