def load(self, filename): keys = [ 'version', 'imageData', 'imagePath', 'shapes', # polygonal annotations 'flags', # image level flags 'imageHeight', 'imageWidth', ] try: with open(filename, 'rb' if PY2 else 'r') as f: data = json.load(f) version = data.get('version') if version is None: logger.warn('Loading JSON file ({}) of unknown version'.format( filename)) elif version.split('.')[0] != __version__.split('.')[0]: logger.warn('This JSON file ({}) may be incompatible with ' 'current labelme. version in file: {}, ' 'current version: {}'.format( filename, version, __version__)) if data['imageData'] is not None: imageData = base64.b64decode(data['imageData']) if PY2 and QT4: imageData = utils.img_data_to_png_data(imageData) else: # relative path from label file to relative path from cwd imagePath = osp.join(osp.dirname(filename), data['imagePath']) imageData = self.load_image_file(imagePath) flags = data.get('flags') or {} imagePath = data['imagePath'] self._check_image_height_and_width( base64.b64encode(imageData).decode('utf-8'), data.get('imageHeight'), data.get('imageWidth'), ) shapes = [ dict(label=s['label'], points=s['points'], shape_type=s.get('shape_type', 'polygon'), flags=s.get('flags', {}), group_id=s.get('group_id')) for s in data['shapes'] ] except Exception as e: raise LabelFileError(e) otherData = {} for key, value in data.items(): if key not in keys: otherData[key] = value # Only replace data after everything is loaded. self.flags = flags self.shapes = shapes self.imagePath = imagePath self.imageData = imageData self.filename = filename self.otherData = otherData
def update_dict(target_dict, new_dict, validate_item=None): for key, value in new_dict.items(): if validate_item: validate_item(key, value) if key not in target_dict: logger.warn("Skipping unexpected key in config: {}".format(key)) continue if isinstance(target_dict[key], dict) and isinstance(value, dict): update_dict(target_dict[key], value, validate_item=validate_item) else: target_dict[key] = value
def update_dict(target_dict, new_dict, validate_item=None): for key, value in new_dict.items(): if validate_item: validate_item(key, value) if key not in target_dict: logger.warn('Skipping unexpected key in config: {}' .format(key)) continue if isinstance(target_dict[key], dict) and \ isinstance(value, dict): update_dict(target_dict[key], value, validate_item=validate_item) else: target_dict[key] = value
def lblsave(filename, lbl): if osp.splitext(filename)[1] != '.png': filename += '.png' # Assume label ranses [-1, 254] for int32, # and [0, 255] for uint8 as VOC. if lbl.min() >= -1 and lbl.max() < 255: lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode='P') colormap = label_colormap(255) lbl_pil.putpalette((colormap * 255).astype(np.uint8).flatten()) lbl_pil.save(filename) else: logger.warn('[%s] Cannot save the pixel-wise class label as PNG, ' 'so please use the npy file.' % filename)
def get_default_config(): config_file = osp.join(here, "default_config.yaml") with open(config_file) as f: config = yaml.safe_load(f) # save default config to ~/.labelmerc user_config_file = osp.join(osp.expanduser("~"), ".labelmerc") if not osp.exists(user_config_file): try: shutil.copy(config_file, user_config_file) except Exception: logger.warn("Failed to save config: {}".format(user_config_file)) return config
def get_default_config(): config_file = osp.join(here, 'default_config.yaml') with open(config_file) as f: config = yaml.load(f) # save default config to ~/.labelmerc user_config_file = osp.join(osp.expanduser('~'), '.labelmerc') if not osp.exists(user_config_file): try: shutil.copy(config_file, user_config_file) except Exception: logger.warn('Failed to save config: {}'.format(user_config_file)) return config
def get_default_config(): config_file = osp.join(here, 'default_config.yaml') with open(config_file) as f: config = yaml.safe_load(f) # save default config to ~/.labelmerc user_config_file = osp.join(osp.expanduser('~'), '.labelmerc_v1_0_1') if not osp.exists(user_config_file): try: shutil.copy(config_file, user_config_file) except Exception: logger.warn('Failed to save config: {}'.format(user_config_file)) return config
def on_message(self, title, message, kind=None): log_msg = 'Show message: {}'.format(message) mb = QtWidgets.QMessageBox if kind == MessageType.Warning: logger.warn(log_msg) mb.warning(self, title, message) elif kind == MessageType.Error: logger.error(log_msg) mb.critical(self, title, message) elif kind == MessageType.Question: logger.info(log_msg) mb.question(self, title, message) else: logger.info(log_msg) mb.information(self, title, message)
def labelme_shapes_to_label(img_shape, shapes): logger.warn('labelme_shapes_to_label is deprecated, so please use ' 'shapes_to_label.') label_name_to_value = {'_background_': 0} for shape in shapes: label_name = shape['label'] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value lbl, _ = shapes_to_label(img_shape, shapes, label_name_to_value) return lbl, label_name_to_value
def labelme_shapes_to_label(img_shape, shapes): logger.warn("labelme_shapes_to_label is deprecated, so please use " "shapes_to_label.") label_name_to_value = {"_background_": 0} for shape in shapes: label_name = shape["label"] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value lbl, _ = shapes_to_label(img_shape, shapes, label_name_to_value) return lbl, label_name_to_value
def get_default_config(): config_file = osp.join(here, 'default_config.yaml') with open(config_file) as f: config = yaml.safe_load(f) # save default config to ~/.labelmerc user_config_file = osp.join(osp.expanduser('~'), '.labelmerc') if not osp.exists(user_config_file): copy_default_config_to_user(config_file, user_config_file) else: with open(user_config_file) as f: user_config = yaml.safe_load(f) if user_config['version'] != config['version']: copy_default_config_to_user(config_file, user_config_file) logger.warn('Replacing older version user config: {}'.format( user_config_file)) return config
def __init__(self, text="Enter object label", parent=None, labels=None, sub_labels=None, sort_labels=True, show_text_field=True, completion="startswith", fit_to_content=None, flags=None, app=None): if fit_to_content is None: fit_to_content = {"row": False, "column": True} self._fit_to_content = fit_to_content super(LabelDialog, self).__init__(parent) # disable default button. Use default close button will have bug # that sub window setting will be reset and can not modify again. # QtCore.Qt.Dialog setting will be reseted. self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False) self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False) self.edit = LabelQLineEdit() self.edit.setPlaceholderText(text) self.edit.setValidator(labelme.utils.labelValidator()) self.edit.editingFinished.connect(self.postProcess) if flags: self.edit.textChanged.connect(self.updateFlags) self.edit_group_id = QtWidgets.QLineEdit() self.edit_group_id.setPlaceholderText("Group ID") self.edit_group_id.setValidator( QtGui.QRegExpValidator(QtCore.QRegExp(r"\d*"), None)) layout = QtWidgets.QVBoxLayout() if show_text_field: layout_edit = QtWidgets.QHBoxLayout() layout_edit.addWidget(self.edit, 6) layout_edit.addWidget(self.edit_group_id, 2) layout.addLayout(layout_edit) ### cc region threshold self.cc_threshold_ui = [] ## slider defaultValue = 6 self.sl = QSlider(Qt.Horizontal) self.sl.setMinimum(0) self.sl.setMaximum(100) self.sl.setValue(defaultValue) self.sl.valueChanged.connect(self.sl_valuechange) ## label show slider value self.slLabel = QLabel("") self.slLabel.setText(str(defaultValue)) self.slLabel.setAlignment(Qt.AlignCenter) ## tie slider and label together slider_set = QtWidgets.QHBoxLayout() slider_set.addWidget(self.sl, 6) slider_set.addWidget(self.slLabel, 2) ## add to total layout self.cc_threshold_ui.append(self.sl) self.cc_threshold_ui.append(self.slLabel) layout.addLayout(slider_set) ### text box attribute self.text_box_ui = [] text_box_set = QtWidgets.QVBoxLayout() ## column of text tmpHor = QtWidgets.QHBoxLayout() self.text_cols = QtWidgets.QLineEdit("4") self.text_cols.setPlaceholderText("") self.text_cols.setValidator( QtGui.QRegExpValidator(QtCore.QRegExp(r"\d*"), None)) # label self.text_cols_label = QLabel("Columns of Text") self.text_cols_label.setAlignment(Qt.AlignLeft) tmpHor.addWidget(self.text_cols_label, 5) tmpHor.addWidget(self.text_cols, 5) # add to ui group self.text_box_ui.append(self.text_cols_label) self.text_box_ui.append(self.text_cols) text_box_set.addLayout(tmpHor) ## rows of text tmpHor = QtWidgets.QHBoxLayout() self.text_rows = QtWidgets.QLineEdit("4") self.text_rows.setPlaceholderText("") self.text_rows.setValidator( QtGui.QRegExpValidator(QtCore.QRegExp(r"\d*"), None)) # label self.text_rows_label = QLabel("Rows of Text") self.text_rows_label.setAlignment(Qt.AlignLeft) tmpHor.addWidget(self.text_rows_label, 5) tmpHor.addWidget(self.text_rows, 5) # add to ui group self.text_box_ui.append(self.text_rows_label) self.text_box_ui.append(self.text_rows) text_box_set.addLayout(tmpHor) ## generate button self.generateBoxbb = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Apply | QtWidgets.QDialogButtonBox.Reset, QtCore.Qt.Horizontal, self) self.generateBoxbb.button(self.generateBoxbb.Apply).clicked.connect( self.setTextBoxAttribute) self.generateBoxbb.button(self.generateBoxbb.Reset).clicked.connect( self.resetTextBoxAttribute) # add to ui group self.text_box_ui.append(self.generateBoxbb) text_box_set.addWidget(self.generateBoxbb, alignment=QtCore.Qt.AlignRight) ## add to total layout layout.addLayout(text_box_set) # buttons self.buttonBox = bb = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self, ) bb.button(bb.Ok).setIcon(labelme.utils.newIcon("done")) bb.button(bb.Cancel).setIcon(labelme.utils.newIcon("undo")) bb.accepted.connect(self.validate) bb.rejected.connect(self.reject) layout.addWidget(bb) # label_list self.labelList = QtWidgets.QListWidget() if self._fit_to_content["row"]: self.labelList.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) if self._fit_to_content["column"]: self.labelList.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self._sort_labels = sort_labels if labels: self.labelList.addItems(labels) if self._sort_labels: self.labelList.sortItems() else: self.labelList.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.labelList.currentItemChanged.connect(self.labelSelected) self.labelList.itemDoubleClicked.connect(self.labelDoubleClicked) self.edit.setListWidget(self.labelList) layout.addWidget(self.labelList) # sub label list self.sub_labelList = QtWidgets.QListWidget() if self._fit_to_content["row"]: self.sub_labelList.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) if self._fit_to_content["column"]: self.sub_labelList.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) if labels: self.sub_labelList.addItems(sub_labels) self.sub_labelList.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.sub_labelList.currentItemChanged.connect(self.labelSelected) # make sure main label has content self.sub_labelList.itemDoubleClicked.connect(self.labelDoubleClicked) self.edit.setListWidget(self.sub_labelList) layout.addWidget(self.sub_labelList) # label_flags if flags is None: flags = {} self._flags = flags self.flagsLayout = QtWidgets.QVBoxLayout() self.resetFlags() layout.addItem(self.flagsLayout) self.edit.textChanged.connect(self.updateFlags) self.setLayout(layout) # completion completer = QtWidgets.QCompleter() if not QT5 and completion != "startswith": logger.warn("completion other than 'startswith' is only " "supported with Qt5. Using 'startswith'") completion = "startswith" if completion == "startswith": completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) # Default settings. # completer.setFilterMode(QtCore.Qt.MatchStartsWith) elif completion == "contains": completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion) completer.setFilterMode(QtCore.Qt.MatchContains) else: raise ValueError("Unsupported completion: {}".format(completion)) completer.setModel(self.labelList.model()) self.completer = completer self.edit.setCompleter(completer) # sub completion completer = QtWidgets.QCompleter() if not QT5 and completion != "startswith": logger.warn("completion other than 'startswith' is only " "supported with Qt5. Using 'startswith'") completion = "startswith" if completion == "startswith": completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) # Default settings. # completer.setFilterMode(QtCore.Qt.MatchStartsWith) elif completion == "contains": completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion) completer.setFilterMode(QtCore.Qt.MatchContains) else: raise ValueError("Unsupported completion: {}".format(completion)) completer.setModel(self.sub_labelList.model()) self.sub_completer = completer # mine # self.inEdit = False self.app = app self.sub_window = SubWindow(self)
def __init__( self, text="Enter object label", parent=None, labels=None, sort_labels=True, show_text_field=True, completion="startswith", fit_to_content=None, flags=None, ): if fit_to_content is None: fit_to_content = {"row": False, "column": True} self._fit_to_content = fit_to_content super(LabelDialog, self).__init__(parent) self.edit = LabelQLineEdit() self.edit.setPlaceholderText(text) self.edit.setValidator(labelme.utils.labelValidator()) self.edit.editingFinished.connect(self.postProcess) if flags: self.edit.textChanged.connect(self.updateFlags) self.edit_group_id = QtWidgets.QLineEdit() self.edit_group_id.setPlaceholderText("Group ID") self.edit_group_id.setValidator( QtGui.QRegExpValidator(QtCore.QRegExp(r"\d*"), None)) layout = QtWidgets.QVBoxLayout() if show_text_field: layout_edit = QtWidgets.QHBoxLayout() layout_edit.addWidget(self.edit, 6) layout_edit.addWidget(self.edit_group_id, 2) layout.addLayout(layout_edit) # buttons self.buttonBox = bb = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self, ) bb.button(bb.Ok).setIcon(labelme.utils.newIcon("done")) bb.button(bb.Cancel).setIcon(labelme.utils.newIcon("undo")) bb.accepted.connect(self.validate) bb.rejected.connect(self.reject) layout.addWidget(bb) # label_list self.labelList = QtWidgets.QListWidget() if self._fit_to_content["row"]: self.labelList.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) if self._fit_to_content["column"]: self.labelList.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self._sort_labels = sort_labels if labels: self.labelList.addItems(labels) if self._sort_labels: self.labelList.sortItems() else: self.labelList.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.labelList.currentItemChanged.connect(self.labelSelected) self.labelList.itemDoubleClicked.connect(self.labelDoubleClicked) self.edit.setListWidget(self.labelList) layout.addWidget(self.labelList) # label_flags if flags is None: flags = {} self._flags = flags self.flagsLayout = QtWidgets.QVBoxLayout() self.resetFlags() layout.addItem(self.flagsLayout) self.edit.textChanged.connect(self.updateFlags) self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.slider.setRange(0, 10) self.slider.setValue(4) layout.addWidget(self.slider) self.setLayout(layout) # completion completer = QtWidgets.QCompleter() if not QT5 and completion != "startswith": logger.warn("completion other than 'startswith' is only " "supported with Qt5. Using 'startswith'") completion = "startswith" if completion == "startswith": completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) # Default settings. # completer.setFilterMode(QtCore.Qt.MatchStartsWith) elif completion == "contains": completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion) completer.setFilterMode(QtCore.Qt.MatchContains) else: raise ValueError("Unsupported completion: {}".format(completion)) completer.setModel(self.labelList.model()) self.edit.setCompleter(completer)
def copy_default_config_to_user(config_file, user_config_file): try: shutil.copy(config_file, user_config_file) except Exception: logger.warn('Failed to save config: {}'.format(user_config_file))
def __init__(self, text="Enter object label", parent=None, labels=None, sort_labels=True, show_text_field=True, completion='startswith', fit_to_content=None, flags=None): if fit_to_content is None: fit_to_content = {'row': False, 'column': True} self._fit_to_content = fit_to_content super(LabelDialog, self).__init__(parent) self.edit = LabelQLineEdit() self.edit.setPlaceholderText(text) self.edit.setValidator(labelme.utils.labelValidator()) self.edit.editingFinished.connect(self.postProcess) if flags: self.edit.textChanged.connect(self.updateFlags) layout = QtWidgets.QVBoxLayout() if show_text_field: layout.addWidget(self.edit) # buttons self.buttonBox = bb = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self, ) bb.button(bb.Ok).setIcon(labelme.utils.newIcon('done')) bb.button(bb.Cancel).setIcon(labelme.utils.newIcon('undo')) bb.accepted.connect(self.validate) bb.rejected.connect(self.reject) layout.addWidget(bb) # label_list self.labelList = QtWidgets.QListWidget() if self._fit_to_content['row']: self.labelList.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) if self._fit_to_content['column']: self.labelList.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self._sort_labels = sort_labels if labels: self.labelList.addItems(labels) if self._sort_labels: self.labelList.sortItems() else: self.labelList.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.labelList.currentItemChanged.connect(self.labelSelected) self.edit.setListWidget(self.labelList) layout.addWidget(self.labelList) # label_flags if flags is None: flags = {} self._flags = flags self.flagsLayout = QtWidgets.QVBoxLayout() self.resetFlags() layout.addItem(self.flagsLayout) self.edit.textChanged.connect(self.updateFlags) self.setLayout(layout) # completion completer = QtWidgets.QCompleter() if not QT5 and completion != 'startswith': logger.warn("completion other than 'startswith' is only " "supported with Qt5. Using 'startswith'") completion = 'startswith' if completion == 'startswith': completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) # Default settings. # completer.setFilterMode(QtCore.Qt.MatchStartsWith) elif completion == 'contains': completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion) completer.setFilterMode(QtCore.Qt.MatchContains) else: raise ValueError('Unsupported completion: {}'.format(completion)) completer.setModel(self.labelList.model()) self.edit.setCompleter(completer)
def load(self, filename): keys = [ "version", 'Patient_Name', 'Patient_ID', 'Modality', 'Study_Date', "imageData", "imagePath", "shapes", # polygonal annotations "flags", # image level flags "imageHeight", "imageWidth", ] shape_keys = [ "label", "points", "group_id", "shape_type", "flags", ] try: with open(filename, "r") as f: data = json.load(f) version = data.get("version") if version is None: logger.warn( "Loading JSON file ({}) of unknown version".format( filename ) ) elif version.split(".")[0] != __version__.split(".")[0]: logger.warn( "This JSON file ({}) may be incompatible with " "current labelme. version in file: {}, " "current version: {}".format( filename, version, __version__ ) ) if data["imageData"] is not None: imageData = base64.b64decode(data["imageData"]) if PY2 and QT4: imageData = utils.img_data_to_png_data(imageData) else: # relative path from label file to relative path from cwd imagePath = osp.join(osp.dirname(filename), data["imagePath"]) imageData = self.load_image_file(imagePath) flags = data.get("flags") or {} imagePath = data["imagePath"] Patient_Name = data['Patient_Name'] Patient_ID = data['Patient_ID'] Modality = data['Modality'] Study_Date = data['Study_Date'] self._check_image_height_and_width( base64.b64encode(imageData).decode("utf-8"), data.get("imageHeight"), data.get("imageWidth"), ) shapes = [ dict( label=s["label"], points=s["points"], shape_type=s.get("shape_type", "polygon"), flags=s.get("flags", {}), group_id=s.get("group_id"), other_data={ k: v for k, v in s.items() if k not in shape_keys }, ) for s in data["shapes"] ] except Exception as e: raise LabelFileError(e) otherData = {} for key, value in data.items(): if key not in keys: otherData[key] = value # Only replace data after everything is loaded. self.flags = flags self.shapes = shapes self.Patient_Name = Patient_Name self.Patient_ID = Patient_ID self.Modality = Modality self.Study_Date = Study_Date self.imagePath = imagePath self.imageData = imageData self.filename = filename self.otherData = otherData
def __init__(self, text="Enter object label", parent=None, labels=None, sort_labels=True, show_text_field=True, completion='startswith', fit_to_content=None): if fit_to_content is None: fit_to_content = {'row': False, 'column': True} self._fit_to_content = fit_to_content super(LabelDialog, self).__init__(parent) self.edit = LabelQLineEdit() self.edit.setPlaceholderText(text) self.edit.setValidator(labelme.utils.labelValidator()) self.edit.editingFinished.connect(self.postProcess) layout = QtWidgets.QVBoxLayout() if show_text_field: layout.addWidget(self.edit) # buttons self.buttonBox = bb = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self, ) bb.button(bb.Ok).setIcon(labelme.utils.newIcon('done')) bb.button(bb.Cancel).setIcon(labelme.utils.newIcon('undo')) bb.accepted.connect(self.validate) bb.rejected.connect(self.reject) layout.addWidget(bb) # label_list self.labelList = QtWidgets.QListWidget() if self._fit_to_content['row']: self.labelList.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff ) if self._fit_to_content['column']: self.labelList.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff ) self._sort_labels = sort_labels if labels: self.labelList.addItems(labels) if self._sort_labels: self.labelList.sortItems() else: self.labelList.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.labelList.currentItemChanged.connect(self.labelSelected) self.edit.setListWidget(self.labelList) layout.addWidget(self.labelList) self.setLayout(layout) # completion completer = QtWidgets.QCompleter() if not QT5 and completion != 'startswith': logger.warn( "completion other than 'startswith' is only " "supported with Qt5. Using 'startswith'" ) completion = 'startswith' if completion == 'startswith': completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion) # Default settings. # completer.setFilterMode(QtCore.Qt.MatchStartsWith) elif completion == 'contains': completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion) completer.setFilterMode(QtCore.Qt.MatchContains) else: raise ValueError('Unsupported completion: {}'.format(completion)) completer.setModel(self.labelList.model()) self.edit.setCompleter(completer)