# -*- coding: utf-8 -*- # @Author : LG from PyQt5 import QtWidgets, QtCore, QtGui from sam_ann.ui.MainWindow import Ui_MainWindow from sam_ann.widgets.setting_dialog import SettingDialog from sam_ann.widgets.category_choice_dialog import CategoryChoiceDialog from sam_ann.widgets.category_edit_dialog import CategoryEditDialog from sam_ann.widgets.category_dock_widget import CategoriesDockWidget from sam_ann.widgets.annos_dock_widget import AnnosDockWidget from sam_ann.widgets.files_dock_widget import FilesDockWidget from sam_ann.widgets.info_dock_widget import InfoDockWidget from sam_ann.widgets.right_button_menu import RightButtonMenu from sam_ann.widgets.shortcut_dialog import ShortcutDialog from sam_ann.widgets.about_dialog import AboutDialog from sam_ann.widgets.ISAT_to_VOC_dialog import ISATtoVOCDialog from sam_ann.widgets.ISAT_to_COCO_dialog import ISATtoCOCODialog from sam_ann.widgets.ISAT_to_LABELME_dialog import ISATtoLabelMeDialog from sam_ann.widgets.COCO_to_ISAT_dialog import COCOtoISATDialog from sam_ann.widgets.canvas import AnnotationScene, AnnotationView from sam_ann.configs import STATUSMode, MAPMode, load_config, save_config, CONFIG_FILE, DEFAULT_CONFIG_FILE, CHECKPOINTS from sam_ann.annotation import Object, Annotation from sam_ann.widgets.polygon import Polygon from sam_ann.configs import BASE_DIR import os from PIL import Image import functools import imgviz import numpy as np from sam_ann.segment_any.segment_any import SegAny from sam_ann.segment_any.gpu_resource import GPUResource_Thread, osplatform import sam_ann.icons_rc class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.image_root: str = None self.label_root:str = None self.files_list: list = [] self.current_index = None self.current_file_index: int = None self.current_cat = '__background__' self.current_group = 1 self.config_file = CONFIG_FILE if os.path.exists(CONFIG_FILE) else DEFAULT_CONFIG_FILE self.saved = True self.can_be_annotated = True self.load_finished = False self.polygons:list = [] self.image_changed = False self.png_palette = None # 图像拥有调色盘,说明是单通道的标注png文件 self.instance_cmap = imgviz.label_colormap() self.map_mode = MAPMode.LABEL # 标注目标 self.current_label:Annotation = None self.use_segment_anything = False self.gpu_resource_thread = None self.pre_segany = '' self.segany = None self.init_ui() self.reload_cfg() self.init_connect() self.reset_action() def init_segment_anything(self, model_name, reload=False): if model_name == '': self.use_segment_anything = False for name, action in self.pths_actions.items(): action.setChecked(model_name == name) return model_path = os.path.join(CHECKPOINTS, model_name) if not os.path.exists(model_path): QtWidgets.QMessageBox.warning(self, 'Warning', 'The checkpoint of [Segment anything] not existed. If you want use quick annotate, please download from {}'.format( 'https://github.com/facebookresearch/segment-anything#model-checkpoints')) for name, action in self.pths_actions.items(): action.setChecked(model_name == name) self.use_segment_anything = False return try: if self.segany is None: self.segany = SegAny(model_path) elif model_name != self.pre_segany: self.segany = SegAny(model_path) self.pre_segany = model_name except Exception as e: print(e) QtWidgets.QMessageBox.warning(self, 'Warning', 'The model of [Segment anything] is not valid. If you want use quick annotate, please download from {}'.format( 'https://github.com/facebookresearch/segment-anything#model-checkpoints')) for name, action in self.pths_actions.items(): action.setChecked(model_name == name) self.use_segment_anything = False return self.use_segment_anything = True self.statusbar.showMessage('Use the checkpoint named {}.'.format(model_name), 3000) for name, action in self.pths_actions.items(): action.setChecked(model_name==name) if self.use_segment_anything: if self.segany.device != 'cpu': if self.gpu_resource_thread is None: self.gpu_resource_thread = GPUResource_Thread() self.gpu_resource_thread.message.connect(self.labelGPUResource.setText) self.gpu_resource_thread.start() else: self.labelGPUResource.setText('cpu') else: self.labelGPUResource.setText('segment anything unused.') if self.current_index is None or ( -1> self.current_index >= len(self.files_list)): return file_path = os.path.join(self.image_root, self.files_list[self.current_index]) image_data = np.array(Image.open(file_path)) if image_data.ndim == 3 and image_data.shape[-1] == 3: # 三通道图 self.segany.set_image(image_data) elif image_data.ndim == 2: # 单通道图 image_data = image_data[:, :, np.newaxis] image_data = np.repeat(image_data, 3, axis=2) # 转换为三通道 self.segany.set_image(image_data) elif image_data.ndim == 3 and image_data.shape[-1] > 3: # 多通道 self.segany.set_image(image_data[:,:,:3]) self.statusbar.showMessage("Segment anything only use the 3 dim with shape {} .".format(image_data.shape)) else: self.statusbar.showMessage("Segment anything don't support the image with shape {} .".format(image_data.shape)) self.image_changed = False self.show_image(self.current_index) # if self.current_index is not None: # self.image_changed = False # self.show_image(self.current_index) def init_ui(self): #q self.setting_dialog = SettingDialog(parent=self, mainwindow=self) self.categories_dock_widget = CategoriesDockWidget(mainwindow=self) self.categories_dock.setWidget(self.categories_dock_widget) self.annos_dock_widget = AnnosDockWidget(mainwindow=self) self.annos_dock.setWidget(self.annos_dock_widget) self.files_dock_widget = FilesDockWidget(mainwindow=self) self.files_dock.setWidget(self.files_dock_widget) self.info_dock_widget = InfoDockWidget(mainwindow=self) self.info_dock.setWidget(self.info_dock_widget) self.scene = AnnotationScene(mainwindow=self) self.category_choice_widget = CategoryChoiceDialog(self, mainwindow=self, scene=self.scene) self.category_edit_widget = CategoryEditDialog(self, self, self.scene) self.ISAT_to_VOC_dialog = ISATtoVOCDialog(self, mainwindow=self) self.ISAT_to_COCO_dialog = ISATtoCOCODialog(self, mainwindow=self) self.ISAT_to_LABELME_dialog = ISATtoLabelMeDialog(self, mainwindow=self) self.COCO_to_ISAT_dialog = COCOtoISATDialog(self, mainwindow=self) self.view = AnnotationView(parent=self) self.view.setScene(self.scene) self.setCentralWidget(self.view) self.right_button_menu = RightButtonMenu(mainwindow=self) self.right_button_menu.addAction(self.actionEdit) self.right_button_menu.addAction(self.actionTo_top) self.right_button_menu.addAction(self.actionTo_bottom) self.shortcut_dialog = ShortcutDialog(self) self.about_dialog = AboutDialog(self) self.labelGPUResource = QtWidgets.QLabel('') self.labelGPUResource.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight) self.labelGPUResource.setFixedWidth(180) self.statusbar.addPermanentWidget(self.labelGPUResource) self.labelCoord = QtWidgets.QLabel('') self.labelCoord.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight) self.labelCoord.setFixedWidth(150) self.statusbar.addPermanentWidget(self.labelCoord) self.labelData = QtWidgets.QLabel('') self.labelData.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight) self.labelData.setFixedWidth(150) self.statusbar.addPermanentWidget(self.labelData) # model_names = sorted([pth for pth in os.listdir(CHECKPOINTS) if pth.endswith('.pth') or pth.endswith('.pt')]) self.pths_actions = {} for model_name in model_names: action = QtWidgets.QAction(self) action.setObjectName("actionZoom_in") action.triggered.connect(functools.partial(self.init_segment_anything, model_name)) action.setText("{}".format(model_name)) action.setCheckable(True) self.pths_actions[model_name] = action self.menuSAM_model.addAction(action) # mask alpha self.toolBar.addSeparator() self.mask_aplha = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal, self) self.mask_aplha.setFixedWidth(50) self.mask_aplha.setStatusTip('Mask alpha.') self.mask_aplha.setToolTip('Mask alpha') self.mask_aplha.setMaximum(10) self.mask_aplha.setMinimum(3) self.mask_aplha.valueChanged.connect(self.change_mask_aplha) self.toolBar.addWidget(self.mask_aplha) # vertex size self.toolBar.addSeparator() self.vertex_size = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal, self) self.vertex_size.setFixedWidth(50) self.vertex_size.setStatusTip('Vertex size.') self.vertex_size.setToolTip('Vertex size') self.vertex_size.setMaximum(10) self.vertex_size.setMinimum(2) self.vertex_size.valueChanged.connect(self.change_vertex_size) self.toolBar.addWidget(self.vertex_size) self.trans = QtCore.QTranslator() def translate(self, language='zh'): if language == 'zh': self.trans.load('ui/zh_CN') else: self.trans.load('ui/en') self.actionChinese.setChecked(language=='zh') self.actionEnglish.setChecked(language=='en') _app = QtWidgets.QApplication.instance() _app.installTranslator(self.trans) self.retranslateUi(self) self.info_dock_widget.retranslateUi(self.info_dock_widget) self.annos_dock_widget.retranslateUi(self.annos_dock_widget) self.files_dock_widget.retranslateUi(self.files_dock_widget) self.category_choice_widget.retranslateUi(self.category_choice_widget) self.category_edit_widget.retranslateUi(self.category_edit_widget) self.setting_dialog.retranslateUi(self.setting_dialog) self.about_dialog.retranslateUi(self.about_dialog) self.shortcut_dialog.retranslateUi(self.shortcut_dialog) self.ISAT_to_VOC_dialog.retranslateUi(self.ISAT_to_VOC_dialog) self.ISAT_to_COCO_dialog.retranslateUi(self.ISAT_to_COCO_dialog) self.ISAT_to_LABELME_dialog.retranslateUi(self.ISAT_to_LABELME_dialog) self.COCO_to_ISAT_dialog.retranslateUi(self.COCO_to_ISAT_dialog) def translate_to_chinese(self): self.translate('zh') self.cfg['language'] = 'zh' def translate_to_english(self): self.translate('en') self.cfg['language'] = 'en' def reload_cfg(self): self.cfg = load_config(self.config_file) label_dict_list = self.cfg.get('label', []) d = {} for label_dict in label_dict_list: category = label_dict.get('name', 'unknow') color = label_dict.get('color', '#000000') d[category] = color self.category_color_dict = d if self.current_index is not None: self.show_image(self.current_index) language = self.cfg.get('language', 'en') self.cfg['language'] = language self.translate(language) contour_mode = self.cfg.get('contour_mode', 'max_only') self.cfg['contour_mode'] = contour_mode self.change_contour_mode(contour_mode) mask_alpha = self.cfg.get('mask_alpha', 0.5) self.cfg['mask_alpha'] = mask_alpha self.mask_aplha.setValue(mask_alpha*10) vertex_size = self.cfg.get('vertex_size', 2) self.cfg['vertex_size'] = int(vertex_size) model_name = self.cfg.get('model_name', '') self.init_segment_anything(model_name) self.categories_dock_widget.update_widget() def set_saved_state(self, is_saved:bool): self.saved = is_saved if self.files_list is not None and self.current_index is not None: if is_saved: self.setWindowTitle(self.current_label.label_path) else: self.setWindowTitle('*{}'.format(self.current_label.label_path)) def open_dir(self): dir = QtWidgets.QFileDialog.getExistingDirectory(self) if dir: self.files_list.clear() self.files_dock_widget.listWidget.clear() files = [] suffixs = tuple(['{}'.format(fmt.data().decode('ascii').lower()) for fmt in QtGui.QImageReader.supportedImageFormats()]) for f in os.listdir(dir): if f.lower().endswith(suffixs): # f = os.path.join(dir, f) files.append(f) files = sorted(files) self.files_list = files self.files_dock_widget.update_widget() self.current_index = 0 self.image_root = dir self.actionOpen_dir.setStatusTip("Image root: {}".format(self.image_root)) if self.label_root is None: self.label_root = dir self.actionSave_dir.setStatusTip("Label root: {}".format(self.label_root)) self.image_changed = True self.show_image(self.current_index) def save_dir(self): dir = QtWidgets.QFileDialog.getExistingDirectory(self) if dir: self.label_root = dir self.actionSave_dir.setStatusTip("Label root: {}".format(self.label_root)) # 刷新图片 if self.current_index is not None: self.show_image(self.current_index) def save(self): if self.current_label is None: return self.current_label.objects.clear() for polygon in self.polygons: object = polygon.to_object() self.current_label.objects.append(object) self.current_label.note = self.info_dock_widget.lineEdit_note.text() self.current_label.save_annotation() # 保存标注文件的同时保存一份isat配置文件 self.save_cfg(os.path.join(self.label_root, 'isat.yaml')) self.set_saved_state(True) def show_image(self, index:int): self.reset_action() self.load_finished = False self.saved = True if not -1 < index < len(self.files_list): self.scene.clear() self.scene.setSceneRect(QtCore.QRectF()) return if not self.image_changed: self.scene.cancel_draw() self.actionSegment_anything.setEnabled(self.use_segment_anything) self.actionPolygon.setEnabled(True) self.actionSave.setEnabled(True) self.actionBit_map.setEnabled(True) self.actionBackspace.setEnabled(True) self.actionFinish.setEnabled(True) self.actionCancel.setEnabled(True) self.actionVisible.setEnabled(True) self.load_finished = True return try: self.current_label = None self.scene.cancel_draw() self.polygons.clear() self.annos_dock_widget.listWidget.clear() file_path = os.path.join(self.image_root, self.files_list[index]) image_data = Image.open(file_path) self.png_palette = image_data.getpalette() if self.png_palette is not None and file_path.endswith('.png'): self.statusbar.showMessage('This is a label file.') self.can_be_annotated = False else: self.can_be_annotated = True if self.can_be_annotated: self.actionSegment_anything.setEnabled(self.use_segment_anything) self.actionPolygon.setEnabled(True) self.actionSave.setEnabled(True) self.actionBit_map.setEnabled(True) self.actionBackspace.setEnabled(True) self.actionFinish.setEnabled(True) self.actionCancel.setEnabled(True) self.actionVisible.setEnabled(True) else: self.actionSegment_anything.setEnabled(False) self.actionPolygon.setEnabled(False) self.actionSave.setEnabled(False) self.actionBit_map.setEnabled(False) self.actionBackspace.setEnabled(False) self.actionFinish.setEnabled(False) self.actionCancel.setEnabled(False) self.actionVisible.setEnabled(False) self.scene.load_image(file_path) self.view.zoomfit() # load label if self.can_be_annotated: self.current_group = 1 _, name = os.path.split(file_path) label_path = os.path.join(self.label_root, '.'.join(name.split('.')[:-1]) + '.json') self.current_label = Annotation(file_path, label_path) # 载入数据 self.current_label.load_annotation() for object in self.current_label.objects: try: group = int(object.group) self.current_group = group+1 if group >= self.current_group else self.current_group except Exception as e: pass polygon = Polygon() self.scene.addItem(polygon) polygon.load_object(object) self.polygons.append(polygon) if self.current_label is not None: self.setWindowTitle('{}'.format(self.current_label.label_path)) else: self.setWindowTitle('{}'.format(file_path)) self.annos_dock_widget.update_listwidget() self.info_dock_widget.update_widget() self.files_dock_widget.set_select(index) self.current_index = index self.files_dock_widget.label_current.setText('{}'.format(self.current_index+1)) self.load_finished = True except Exception as e: print(e) finally: if self.current_index > 0: self.actionPrev.setEnabled(True) else: self.actionPrev.setEnabled(False) if self.current_index < len(self.files_list) - 1: self.actionNext.setEnabled(True) else: self.actionNext.setEnabled(False) def prev_image(self): if self.scene.mode != STATUSMode.VIEW: return if self.current_index is None: return if not self.saved: result = QtWidgets.QMessageBox.question(self, 'Warning', 'Proceed without saved?', QtWidgets.QMessageBox.StandardButton.Yes|QtWidgets.QMessageBox.StandardButton.No, QtWidgets.QMessageBox.StandardButton.No) if result == QtWidgets.QMessageBox.StandardButton.No: return self.current_index = self.current_index - 1 if self.current_index < 0: self.current_index = 0 QtWidgets.QMessageBox.warning(self, 'Warning', 'This is the first picture.') else: self.image_changed = True self.show_image(self.current_index) def next_image(self): if self.scene.mode != STATUSMode.VIEW: return if self.current_index is None: return if not self.saved: result = QtWidgets.QMessageBox.question(self, 'Warning', 'Proceed without saved?', QtWidgets.QMessageBox.StandardButton.Yes|QtWidgets.QMessageBox.StandardButton.No, QtWidgets.QMessageBox.StandardButton.No) if result == QtWidgets.QMessageBox.StandardButton.No: return self.current_index = self.current_index + 1 if self.current_index > len(self.files_list)-1: self.current_index = len(self.files_list)-1 QtWidgets.QMessageBox.warning(self, 'Warning', 'This is the last picture.') else: self.image_changed = True self.show_image(self.current_index, True) def jump_to(self): index = self.files_dock_widget.lineEdit_jump.text() if index: if not index.isdigit(): if index in self.files_list: index = self.files_list.index(index)+1 else: QtWidgets.QMessageBox.warning(self, 'Warning', 'Don`t exist image named: {}'.format(index)) self.files_dock_widget.lineEdit_jump.clear() return index = int(index)-1 if 0 <= index < len(self.files_list): self.image_changed = True self.show_image(index) self.files_dock_widget.lineEdit_jump.clear() else: QtWidgets.QMessageBox.warning(self, 'Warning', 'Index must be in [1, {}].'.format(len(self.files_list))) self.files_dock_widget.lineEdit_jump.clear() self.files_dock_widget.lineEdit_jump.clearFocus() return def cancel_draw(self): self.scene.cancel_draw() def setting(self): self.setting_dialog.load_cfg() self.setting_dialog.show() def add_new_object(self, category, group, segmentation, area, layer, bbox): if self.current_label is None: return object = Object(category=category, group=group, segmentation=segmentation, area=area, layer=layer, bbox=bbox) self.current_label.objects.append(object) def delete_object(self, index:int): if 0 <= index < len(self.current_label.objects): del self.current_label.objects[index] def change_bit_map(self): self.set_labels_visible(True) if self.scene.mode == STATUSMode.CREATE: self.scene.cancel_draw() if self.map_mode == MAPMode.LABEL: # to semantic for polygon in self.polygons: polygon.setEnabled(False) for vertex in polygon.vertexs: vertex.setVisible(False) polygon.change_color(QtGui.QColor(self.category_color_dict.get(polygon.category, '#000000'))) polygon.color.setAlpha(255) polygon.setBrush(polygon.color) self.annos_dock_widget.listWidget.setEnabled(False) self.annos_dock_widget.checkBox_visible.setEnabled(False) self.actionSegment_anything.setEnabled(False) self.actionPolygon.setEnabled(False) self.actionVisible.setEnabled(False) self.map_mode = MAPMode.SEMANTIC semantic_icon = QtGui.QIcon() semantic_icon.addPixmap(QtGui.QPixmap(":/icon/icons/semantic.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBit_map.setIcon(semantic_icon) elif self.map_mode == MAPMode.SEMANTIC: # to instance for polygon in self.polygons: polygon.setEnabled(False) for vertex in polygon.vertexs: vertex.setVisible(False) if polygon.group != '': index = int(polygon.group) index = index % self.instance_cmap.shape[0] rgb = self.instance_cmap[index] else: rgb = self.instance_cmap[0] polygon.change_color(QtGui.QColor(rgb[0], rgb[1], rgb[2], 255)) polygon.color.setAlpha(255) polygon.setBrush(polygon.color) self.annos_dock_widget.listWidget.setEnabled(False) self.annos_dock_widget.checkBox_visible.setEnabled(False) self.actionSegment_anything.setEnabled(False) self.actionPolygon.setEnabled(False) self.actionVisible.setEnabled(False) self.map_mode = MAPMode.INSTANCE instance_icon = QtGui.QIcon() instance_icon.addPixmap(QtGui.QPixmap(":/icon/icons/instance.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBit_map.setIcon(instance_icon) elif self.map_mode == MAPMode.INSTANCE: # to label for polygon in self.polygons: polygon.setEnabled(True) for vertex in polygon.vertexs: # vertex.setEnabled(True) vertex.setVisible(polygon.isVisible()) polygon.change_color(QtGui.QColor(self.category_color_dict.get(polygon.category, '#000000'))) polygon.color.setAlpha(polygon.nohover_alpha) polygon.setBrush(polygon.color) self.annos_dock_widget.listWidget.setEnabled(True) self.annos_dock_widget.checkBox_visible.setEnabled(True) self.actionSegment_anything.setEnabled(self.use_segment_anything) self.actionPolygon.setEnabled(True) self.actionVisible.setEnabled(True) self.map_mode = MAPMode.LABEL label_icon = QtGui.QIcon() label_icon.addPixmap(QtGui.QPixmap(":/icon/icons/照片_pic.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionBit_map.setIcon(label_icon) else: pass def set_labels_visible(self, visible=None): if visible is None: visible = not self.annos_dock_widget.checkBox_visible.isChecked() self.annos_dock_widget.checkBox_visible.setChecked(visible) self.annos_dock_widget.set_all_polygon_visible(visible) def change_contour_mode(self, contour_mode='max_only'): if contour_mode == 'max_only': self.scene.change_contour_mode_to_save_max_only() elif contour_mode == 'external': self.scene.change_contour_mode_to_save_external() self.statusbar.showMessage('Save all external contours will bring some noise.', 3000) elif contour_mode == 'all': self.scene.change_contour_mode_to_save_all() self.statusbar.showMessage('Category of inner contour will be set _background__.', 3000) else: self.scene.change_contour_mode_to_save_max_only() self.statusbar.showMessage('The contour mode [{}] not support.'.format(contour_mode), 3000) self.actionContour_Max_only.setChecked(contour_mode == 'max_only') self.actionContour_External.setChecked(contour_mode == 'external') self.actionContour_All.setChecked(contour_mode == 'all') self.cfg['contour_mode'] = contour_mode def change_mask_aplha(self): value = self.mask_aplha.value() / 10 self.scene.mask_alpha = value self.scene.update_mask() self.cfg['mask_alpha'] = value def change_vertex_size(self): value = self.vertex_size.value() self.cfg['vertex_size'] = value if self.current_index is not None: # TODO: no clear self.image_changed = False self.show_image(self.current_index) def ISAT_to_VOC(self): self.ISAT_to_VOC_dialog.reset_gui() self.ISAT_to_VOC_dialog.show() def ISAT_to_COCO(self): self.ISAT_to_COCO_dialog.reset_gui() self.ISAT_to_COCO_dialog.show() def ISAT_to_LABELME(self): self.ISAT_to_LABELME_dialog.reset_gui() self.ISAT_to_LABELME_dialog.show() def COCO_to_ISAT(self): self.COCO_to_ISAT_dialog.reset_gui() self.COCO_to_ISAT_dialog.show() def help(self): self.shortcut_dialog.show() def about(self): self.about_dialog.show() def save_cfg(self, config_file): save_config(self.cfg, config_file) def exit(self): self.save_cfg(self.config_file) self.close() def closeEvent(self, a0: QtGui.QCloseEvent): self.exit() def init_connect(self): self.actionOpen_dir.triggered.connect(self.open_dir) self.actionSave_dir.triggered.connect(self.save_dir) self.actionPrev.triggered.connect(self.prev_image) self.actionNext.triggered.connect(self.next_image) self.actionSetting.triggered.connect(self.setting) self.actionExit.triggered.connect(self.exit) self.actionSegment_anything.triggered.connect(self.scene.start_segment_anything) self.actionPolygon.triggered.connect(self.scene.start_draw_polygon) self.actionCancel.triggered.connect(self.scene.cancel_draw) self.actionBackspace.triggered.connect(self.scene.backspace) self.actionFinish.triggered.connect(self.scene.finish_draw) self.actionEdit.triggered.connect(self.scene.edit_polygon) self.actionDelete.triggered.connect(self.scene.delete_selected_graph) self.actionSave.triggered.connect(self.save) self.actionTo_top.triggered.connect(self.scene.move_polygon_to_top) self.actionTo_bottom.triggered.connect(self.scene.move_polygon_to_bottom) self.actionZoom_in.triggered.connect(self.view.zoom_in) self.actionZoom_out.triggered.connect(self.view.zoom_out) self.actionFit_wiondow.triggered.connect(self.view.zoomfit) self.actionBit_map.triggered.connect(self.change_bit_map) self.actionVisible.triggered.connect(functools.partial(self.set_labels_visible, None)) self.actionContour_Max_only.triggered.connect(functools.partial(self.change_contour_mode, 'max_only')) self.actionContour_External.triggered.connect(functools.partial(self.change_contour_mode, 'external')) self.actionContour_All.triggered.connect(functools.partial(self.change_contour_mode, 'all')) self.actionToVOC.triggered.connect(self.ISAT_to_VOC) self.actionToCOCO.triggered.connect(self.ISAT_to_COCO) self.actionTo_LabelMe.triggered.connect(self.ISAT_to_LABELME) self.actionFromCOCO.triggered.connect(self.COCO_to_ISAT) self.actionShortcut.triggered.connect(self.help) self.actionAbout.triggered.connect(self.about) self.actionChinese.triggered.connect(self.translate_to_chinese) self.actionEnglish.triggered.connect(self.translate_to_english) self.annos_dock_widget.listWidget.doubleClicked.connect(self.scene.edit_polygon) def reset_action(self): self.actionPrev.setEnabled(False) self.actionNext.setEnabled(False) self.actionSegment_anything.setEnabled(False) self.actionPolygon.setEnabled(False) self.actionEdit.setEnabled(False) self.actionDelete.setEnabled(False) self.actionSave.setEnabled(False) self.actionTo_top.setEnabled(False) self.actionTo_bottom.setEnabled(False) self.actionBit_map.setChecked(False) self.actionBit_map.setEnabled(False)