Skip to content

Commit 35de974

Browse files
authored
[EISeg] Fix bugs/links and add load mask (#3078)
1 parent c19815f commit 35de974

File tree

12 files changed

+252
-32
lines changed

12 files changed

+252
-32
lines changed

EISeg/docs/video.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ EISeg视频标注工具以EISeg交互式分割算法及[MIVOS](https://github.co
2828

2929
| 模型类型 | 适用场景 | 模型结构 | 模型下载地址 | 配套传播模型下载地址 |
3030
| -------- | -------------------------- | -------------- | ------------------------------------------------------------ |-------------|
31-
| 高精度模型 | 通用场景的图像标注 | HRNet18_OCR64 | [static_hrnet18_ocr64_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_cocolvis.zip) | [static_propagation](https://www.wjx.cn/vm/wWw3pRc.aspx) |
32-
| 轻量化模型 | 通用场景的图像标注 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_cocolvis.zip) | [static_propagation](https://www.wjx.cn/vm/wWw3pRc.aspx) |
33-
| 高精度模型 | 通用图像标注场景 | EdgeFlow | [static_edgeflow_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_edgeflow_cocolvis.zip) | [static_propagation](https://www.wjx.cn/vm/wWw3pRc.aspx) |
34-
| 高精度模型 | 人像标注场景 | HRNet18_OCR64 | [static_hrnet18_ocr64_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_human.zip) | [static_propagation](https://www.wjx.cn/vm/wWw3pRc.aspx) |
35-
| 轻量化模型 | 人像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_human.zip) | [static_propagation](https://www.wjx.cn/vm/wWw3pRc.aspx) |
36-
| 轻量化模型 | 医疗肝脏标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_lits](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_lits.zip) | [static_propagation_lits](https://www.wjx.cn/vm/wWw3pRc.aspx) |
37-
| 轻量化模型 | CT椎骨图像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_MRSpineSeg](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_MRSpineSeg.zip) | [static_propagation_spine](https://www.wjx.cn/vm/wWw3pRc.aspx) |
31+
| 高精度模型 | 通用场景的图像标注 | HRNet18_OCR64 | [static_hrnet18_ocr64_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
32+
| 轻量化模型 | 通用场景的图像标注 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
33+
| 高精度模型 | 通用图像标注场景 | EdgeFlow | [static_edgeflow_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_edgeflow_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
34+
| 高精度模型 | 人像标注场景 | HRNet18_OCR64 | [static_hrnet18_ocr64_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_human.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
35+
| 轻量化模型 | 人像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_human.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
36+
| 轻量化模型 | 医疗肝脏标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_lits](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_lits.zip) | [static_propagation_lits](https://paddleseg.bj.bcebos.com/eivseg/static_propagation_lits.zip) |
37+
| 轻量化模型 | CT椎骨图像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_MRSpineSeg](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_MRSpineSeg.zip) | [static_propagation_spine](https://paddleseg.bj.bcebos.com/eivseg/static_propagation_spine.zip) |
3838

3939
## 数据准备
4040
- 由于视频处理计算量较大,推荐使用带显卡带机器进行视频分割和3D医疗图片带标注,并且标注图像帧数不宜超过100帧,若视频超过该帧数,可以通过[cut_video.py](../tool/cut_video.py)来进行视频截取。

EISeg/docs/video_en.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ Before using EISeg, please download the propagation model parameters. If you wan
2626

2727
| Model Type | Applicable Scenarios | Model Architecture | Download Link | Corresponding Propagation Model Download Link |
2828
| -------- |---------------------------------------------------------| -------------- | ------------------------------------------------------------ |----------------------------------------------------------------|
29-
| High Performance Model | Image annotation in generic scenarios | HRNet18_OCR64 | [static_hrnet18_ocr64_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_cocolvis.zip) | [static_propagation](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
30-
| Lightweight Model | Image annotation in generic scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_cocolvis.zip) | [static_propagation](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
31-
| High Performance Model | Image annotation in generic scenarios | EdgeFlow | [static_edgeflow_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_edgeflow_cocolvis.zip) | [static_propagation](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
32-
| High Performance Model | Annotation in portrait scenarios | HRNet18_OCR64 | [static_hrnet18_ocr64_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_human.zip) | [static_propagation](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
33-
| Lightweight Model | Annotation in portrait scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_human.zip) | [static_propagation](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
34-
| Lightweight Model | Annotation of liver in medical scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_lits](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_lits.zip) | [static_propagation_lits](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
35-
| Lightweight Model | Annotation of CT Spinal Structures in medical scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_MRSpineSeg](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_MRSpineSeg.zip) | [static_propagation_spine](https://docs.google.com/forms/d/e/1FAIpQLSc72-EQKVCJnTQIlROY1DYVIYIm50LWyboj70XqIOvHsUa6ng/viewform?usp=sf_link) |
29+
| High Performance Model | Image annotation in generic scenarios | HRNet18_OCR64 | [static_hrnet18_ocr64_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
30+
| Lightweight Model | Image annotation in generic scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
31+
| High Performance Model | Image annotation in generic scenarios | EdgeFlow | [static_edgeflow_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_edgeflow_cocolvis.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
32+
| High Performance Model | Annotation in portrait scenarios | HRNet18_OCR64 | [static_hrnet18_ocr64_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_human.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
33+
| Lightweight Model | Annotation in portrait scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_human.zip) | [static_propagation](https://paddleseg.bj.bcebos.com/eivseg/static_propagation.zip) |
34+
| Lightweight Model | Annotation of liver in medical scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_lits](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_lits.zip) | [static_propagation_lits](https://paddleseg.bj.bcebos.com/eivseg/static_propagation_lits.zip) |
35+
| Lightweight Model | Annotation of CT Spinal Structures in medical scenarios | HRNet18s_OCR48 | [static_hrnet18s_ocr48_MRSpineSeg](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_MRSpineSeg.zip) | [static_propagation_spine](https://paddleseg.bj.bcebos.com/eivseg/static_propagation_spine.zip) |
3636

3737
## Data Preparation
3838

EISeg/eiseg/app.py

+73-17
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from easydict import EasyDict as edict
2424

2525
from qtpy import QtGui, QtCore, QtWidgets
26-
from qtpy.QtWidgets import QMainWindow, QMessageBox, QTableWidgetItem, QApplication
26+
from qtpy.QtWidgets import QMainWindow, QMessageBox, QTableWidgetItem, QApplication, QDialog
2727
from qtpy.QtGui import QImage, QPixmap
2828
from qtpy.QtCore import Qt, QByteArray, QVariant, QCoreApplication
2929
import cv2
@@ -33,14 +33,15 @@
3333
import paddle.nn.functional as F
3434

3535
from eiseg import pjpath, __APPNAME__, logger
36-
from widget import ShortcutWidget, PolygonAnnotation, LabelCorresWidget
36+
from widget import ShortcutWidget, PolygonAnnotation, LabelCorresWidget, CustomDialog
3737
from controller import InteractiveController
3838
from ui import Ui_EISeg
3939
import util
4040
from util import COCO
4141
from util import check_cn, normcase
4242
from util.voc import VocAnnotations
4343
from util.jsencoder import JSEncoder
44+
from util.masktococo import saveMaskToCOCO
4445

4546
import plugin.remotesensing as rs
4647
from plugin.medical import med
@@ -216,11 +217,13 @@ def __init__(self, parent=None):
216217

217218
self.formats = [
218219
img_ext, # 自然图像
219-
[".dcm"], # 医学影像
220+
[".dcm", ".tif", ".tiff"], # 医学影像(tiff格式的X光数据)
220221
rs_ext, # 遥感影像
221222
video_ext, # 视频
222223
]
223224

225+
self.rs_tiff_support = None
226+
224227
# 遥感
225228
self.raster = None
226229
self.grid = None
@@ -327,6 +330,12 @@ def initActions(self):
327330
"open_folder",
328331
"OpenFolder",
329332
tr("打开一个文件夹下所有的图像进行标注"), )
333+
convert_mask = action(
334+
tr("&加载分割标签图像"),
335+
self.loadMaskImage,
336+
"convert_mask",
337+
"Convert",
338+
tr("将分割的图像和图像标签转换为EISeg可以读取多边形的格式"), )
330339
change_output_dir = action(
331340
tr("&改变标签保存路径"),
332341
partial(self.changeOutputDir, None),
@@ -702,6 +711,7 @@ def newWidget(text, icon, showAction):
702711
fileMenu=(
703712
open_image,
704713
open_folder,
714+
convert_mask,
705715
change_output_dir,
706716
load_param,
707717
clear_recent,
@@ -1419,6 +1429,7 @@ def openFolder(self, inputDir: str=None):
14191429
self.listFiles.clear()
14201430

14211431
# 3. 扫描文件夹下所有图片
1432+
self.rs_tiff_support is None
14221433
# 3.1 获取所有文件名
14231434
imagePaths = os.listdir(inputDir)
14241435
exts = tuple(f for fmts in self.formats for f in fmts)
@@ -1428,9 +1439,7 @@ def openFolder(self, inputDir: str=None):
14281439
if len(imagePaths) == 0:
14291440
return
14301441
# 3.2 设置默认输出路径
1431-
if self.outputDir is None:
1432-
# 没设置为文件夹下的 label 文件夹
1433-
self.outputDir = osp.join(inputDir, "label")
1442+
self.outputDir = osp.join(inputDir, "label")
14341443
if not osp.exists(self.outputDir):
14351444
os.makedirs(self.outputDir)
14361445
# 3.3 有重名图片,标签保留原来拓展名
@@ -1477,6 +1486,18 @@ def loadImage(self, path):
14771486
image = None
14781487
self.video_first = None
14791488

1489+
# tiff数据判断类型
1490+
if path.lower().endswith((".tif", ".tiff")) and self.rs_tiff_support is None:
1491+
tiff_checked_dialog = CustomDialog(
1492+
self,
1493+
self.tr("tiff格式检查"),
1494+
self.tr("检测到当前图像为tiff格式,请指定其为遥感数据还是医疗数据"),
1495+
self.tr("遥感数据"),
1496+
self.tr("医疗数据")
1497+
)
1498+
if (tiff_checked_dialog.exec_()):
1499+
self.rs_tiff_support = tiff_checked_dialog.rs_support
1500+
14801501
# 直接if会报错,因为打开遥感图像后多波段不存在,现在把遥感图像的单独抽出来了
14811502
# 自然图像
14821503
if path.lower().endswith(tuple(self.formats[0])):
@@ -1493,7 +1514,8 @@ def loadImage(self, path):
14931514
image, _ = self.grid.getGrid(0, 0)
14941515

14951516
# 医学影像
1496-
if path.lower().endswith(tuple(self.formats[1])):
1517+
if path.lower().endswith(tuple(self.formats[1])) and \
1518+
self.rs_tiff_support is not True:
14971519
if not self.dockStatus[5]:
14981520
res = self.warn(
14991521
self.tr("未启用医疗组件"),
@@ -1527,7 +1549,7 @@ def loadImage(self, path):
15271549

15281550
# 遥感图像
15291551
if path.lower().endswith(tuple(self.formats[
1530-
2])): # imghdr.what(path) == "tiff":
1552+
2])) and self.rs_tiff_support: # imghdr.what(path) == "tiff":
15311553
if not self.dockStatus[4]:
15321554
res = self.warn(
15331555
self.tr("未打开遥感组件"),
@@ -1778,6 +1800,7 @@ def finishObject(self):
17781800
color = self.controller.labelList[self.currLabelIdx].color
17791801
self.createPoly(curr_polygon, color)
17801802
if self.video_first is False:
1803+
self._video_pause()
17811804
self.updateImage()
17821805
current_mask = self.getVideoMask()
17831806
if current_mask is not None and len(self.scene.polygon_items) == 0:
@@ -2979,16 +3002,22 @@ def on_play(self):
29793002
self.warn(self.tr("图片格式无法播放"), self.tr("请先加载视频"))
29803003
return
29813004
if self.timer.isActive():
2982-
self.timer.stop()
2983-
self.image = self.video_images[self.video.cursur]
2984-
self.videoPlay.setText(self.tr("播放"))
2985-
self.videoPlay.setIcon(
2986-
QtGui.QIcon(osp.join(pjpath, "resource/Play.png")))
3005+
self._video_pause()
29873006
else:
2988-
self.timer.start(1000 // self.ratio)
2989-
self.videoPlay.setText(self.tr("暂停"))
2990-
self.videoPlay.setIcon(
2991-
QtGui.QIcon(osp.join(pjpath, "resource/Stop.png")))
3007+
self._video_play()
3008+
3009+
def _video_pause(self):
3010+
self.timer.stop()
3011+
self.image = self.video_images[self.video.cursur]
3012+
self.videoPlay.setText(self.tr("播放"))
3013+
self.videoPlay.setIcon(
3014+
QtGui.QIcon(osp.join(pjpath, "resource/Play.png")))
3015+
3016+
def _video_play(self):
3017+
self.timer.start(1000 // self.ratio)
3018+
self.videoPlay.setText(self.tr("暂停"))
3019+
self.videoPlay.setIcon(
3020+
QtGui.QIcon(osp.join(pjpath, "resource/Stop.png")))
29923021

29933022
def getVideoMask(self):
29943023
try:
@@ -3018,6 +3047,7 @@ def on_propgation(self):
30183047
# return
30193048
print('-------------start propgation----------------')
30203049
self.statusbar.showMessage(self.tr("开始传播"))
3050+
self.btnPropagate.setEnabled(False)
30213051
# set object
30223052
self.video.set_objects(int(max(self.video.k, current_mask.max())))
30233053
self.video.set_images(self.video_images)
@@ -3033,6 +3063,7 @@ def on_propgation(self):
30333063
end = time.time()
30343064
print("propagation time cost", end - start)
30353065
self.statusbar.showMessage(self.tr("传播完成!"), 5000)
3066+
self.btnPropagate.setEnabled(True)
30363067
self.video_first = False
30373068
# 传播进度条重置
30383069
self.proPropagete.setValue(0)
@@ -3384,3 +3415,28 @@ def save_labelName_txt(self, path):
33843415
with open(path, "w", encoding="utf-8") as f:
33853416
for label in labelName:
33863417
f.write(label + "\n")
3418+
3419+
def loadMaskImage(self):
3420+
options = (QtWidgets.QFileDialog.ShowDirsOnly |
3421+
QtWidgets.QFileDialog.DontResolveSymlinks)
3422+
if self.settings.value("use_qt_widget", False, type=bool):
3423+
options = options | QtWidgets.QFileDialog.DontUseNativeDialog
3424+
imgDir = QtWidgets.QFileDialog.getExistingDirectory(
3425+
self,
3426+
self.tr("选择图片文件夹") + " - " + __APPNAME__,
3427+
"",
3428+
options, )
3429+
if not osp.exists(imgDir):
3430+
return
3431+
maskDir = QtWidgets.QFileDialog.getExistingDirectory(
3432+
self,
3433+
self.tr("选择标签文件夹") + " - " + __APPNAME__,
3434+
"",
3435+
options, )
3436+
if not osp.exists(maskDir):
3437+
return
3438+
try:
3439+
saveMaskToCOCO(imgDir, maskDir)
3440+
self.statusbar.showMessage(self.tr("转换完成"), 10000)
3441+
except:
3442+
self.statusbar.showMessage(self.tr("转换失败"), 10000)

EISeg/eiseg/controller.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from eiseg import logger
2727
from inference import clicker
2828
from inference.predictor import get_predictor
29-
from models import EISegModel
29+
from eiseg.models import EISegModel
3030
from util import LabelList
3131
from util.vis import draw_with_blend_and_clicks
3232

EISeg/eiseg/resource/Convert.png

8.1 KB
Loading

0 commit comments

Comments
 (0)