From 0fc75bd1d216fa3ce8a242e4b713f647680c16d6 Mon Sep 17 00:00:00 2001 From: Michael Litvin Date: Tue, 7 Sep 2021 02:39:38 +0300 Subject: [PATCH 1/4] Regex filename search --- labelme/app.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/labelme/app.py b/labelme/app.py index 2e5ec2e3b..6f07ca1eb 100644 --- a/labelme/app.py +++ b/labelme/app.py @@ -1987,7 +1987,11 @@ def importDirImages(self, dirpath, pattern=None, load=True): self.fileListWidget.clear() for filename in self.scanAllImages(dirpath): if pattern and pattern not in filename: - continue + try: + if not re.search(pattern, filename): + continue + except re.error: + pass label_file = osp.splitext(filename)[0] + ".json" if self.output_dir: label_file_without_path = osp.basename(label_file) From e2778cb31c8027371ba48b81b5a03e80cc6bc2ad Mon Sep 17 00:00:00 2001 From: Michael Litvin Date: Tue, 7 Sep 2021 02:40:29 +0300 Subject: [PATCH 2/4] os.path.normpath filenames to display paths correctly on Windows --- labelme/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/labelme/app.py b/labelme/app.py index 6f07ca1eb..3bfad7271 100644 --- a/labelme/app.py +++ b/labelme/app.py @@ -2017,7 +2017,7 @@ def scanAllImages(self, folderPath): for root, dirs, files in os.walk(folderPath): for file in files: if file.lower().endswith(tuple(extensions)): - relativePath = osp.join(root, file) + relativePath = os.path.normpath(osp.join(root, file)) images.append(relativePath) images.sort(key=lambda x: x.lower()) return images From a93428d68a66941f7de9cd05f728dfb262fbf4af Mon Sep 17 00:00:00 2001 From: Michael Litvin Date: Tue, 7 Sep 2021 12:17:48 +0300 Subject: [PATCH 3/4] Edit label on double click on shape in canvas --- labelme/app.py | 1 + labelme/widgets/canvas.py | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/labelme/app.py b/labelme/app.py index 3bfad7271..c8f161ce0 100644 --- a/labelme/app.py +++ b/labelme/app.py @@ -169,6 +169,7 @@ def __init__( epsilon=self._config["epsilon"], double_click=self._config["canvas"]["double_click"], num_backups=self._config["canvas"]["num_backups"], + edit_label_method=self.editLabel, ) self.canvas.zoomRequest.connect(self.zoomRequest) diff --git a/labelme/widgets/canvas.py b/labelme/widgets/canvas.py index 6afeedbae..d3c4780cf 100644 --- a/labelme/widgets/canvas.py +++ b/labelme/widgets/canvas.py @@ -1,3 +1,5 @@ +import time + from qtpy import QtCore from qtpy import QtGui from qtpy import QtWidgets @@ -37,7 +39,7 @@ class Canvas(QtWidgets.QWidget): _fill_drawing = False - def __init__(self, *args, **kwargs): + def __init__(self, edit_label_method, *args, **kwargs): self.epsilon = kwargs.pop("epsilon", 10.0) self.double_click = kwargs.pop("double_click", "close") if self.double_click not in [None, "close"]: @@ -78,6 +80,8 @@ def __init__(self, *args, **kwargs): self.movingShape = False self._painter = QtGui.QPainter() self._cursor = CURSOR_DEFAULT + self._lastMouseReleaseTime = 0 + self._editLabelMethod = edit_label_method # Menus: # 0: right-click without selection and dragging of shapes # 1: right-click with selection and dragging of shapes @@ -183,10 +187,7 @@ def selectedVertex(self): def mouseMoveEvent(self, ev): """Update line with last point and current coordinates.""" try: - if QT5: - pos = self.transformPos(ev.localPos()) - else: - pos = self.transformPos(ev.posF()) + pos = self.getMousePos(ev) except AttributeError: return @@ -328,10 +329,7 @@ def removeSelectedPoint(self): self.movingShape = True # Save changes def mousePressEvent(self, ev): - if QT5: - pos = self.transformPos(ev.localPos()) - else: - pos = self.transformPos(ev.posF()) + pos = self.getMousePos(ev) if ev.button() == QtCore.Qt.LeftButton: if self.drawing(): if self.current: @@ -374,7 +372,14 @@ def mousePressEvent(self, ev): self.prevPoint = pos self.repaint() + def getMousePos(self, ev): + return self.transformPos(ev.localPos() if QT5 else ev.posF()) + def mouseReleaseEvent(self, ev): + tm = time.time() + is_double_click = (tm - self._lastMouseReleaseTime) < .4 + self._lastMouseReleaseTime = tm + if ev.button() == QtCore.Qt.RightButton: menu = self.menus[len(self.selectedShapesCopy) > 0] self.restoreCursor() @@ -412,6 +417,10 @@ def mouseReleaseEvent(self, ev): self.movingShape = False + if is_double_click: + if ev.button() == QtCore.Qt.LeftButton and self.editing() and len(self.selectedShapes or []) == 1: + self._editLabelMethod() + def endMove(self, copy): assert self.selectedShapes and self.selectedShapesCopy assert len(self.selectedShapesCopy) == len(self.selectedShapes) From 46311d5fee6a5772207c00d31bdfe677ef2e95c9 Mon Sep 17 00:00:00 2001 From: Michael Litvin Date: Tue, 12 Oct 2021 11:15:05 +0300 Subject: [PATCH 4/4] Toggle all polygons menu with shortcuts --- labelme/app.py | 18 ++++++++++++++++-- labelme/config/default_config.yaml | 4 ++++ labelme/translate/empty.ts | 11 +++++++++++ labelme/translate/zh_CN.ts | 11 +++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/labelme/app.py b/labelme/app.py index c8f161ce0..ed36fc173 100644 --- a/labelme/app.py +++ b/labelme/app.py @@ -425,6 +425,7 @@ def __init__( hideAll = action( self.tr("&Hide\nPolygons"), functools.partial(self.togglePolygons, False), + shortcuts["hide_all_polygons"], icon="eye", tip=self.tr("Hide all polygons"), enabled=False, @@ -432,10 +433,19 @@ def __init__( showAll = action( self.tr("&Show\nPolygons"), functools.partial(self.togglePolygons, True), + shortcuts["show_all_polygons"], icon="eye", tip=self.tr("Show all polygons"), enabled=False, ) + toggleAll = action( + self.tr("&Toggle\nPolygons"), + functools.partial(self.togglePolygons, None), + shortcuts["toggle_all_polygons"], + icon="eye", + tip=self.tr("Toggle all polygons"), + enabled=False, + ) help = action( self.tr("&Tutorial"), @@ -633,7 +643,7 @@ def __init__( editMode, brightnessContrast, ), - onShapesPresent=(saveAs, hideAll, showAll), + onShapesPresent=(saveAs, hideAll, showAll, toggleAll), ) self.canvas.edgeSelected.connect(self.canvasShapeEdgeSelected) @@ -680,6 +690,7 @@ def __init__( None, hideAll, showAll, + toggleAll, None, zoomIn, zoomOut, @@ -1413,8 +1424,11 @@ def brightnessContrast(self, value): self.brightnessContrast_values[self.filename] = (brightness, contrast) def togglePolygons(self, value): + flag = value for item in self.labelList: - item.setCheckState(Qt.Checked if value else Qt.Unchecked) + if value is None: + flag = (item.checkState() == Qt.Unchecked) + item.setCheckState(Qt.Checked if flag else Qt.Unchecked) def loadFile(self, filename=None): """Load the specified file, or the last opened file if None.""" diff --git a/labelme/config/default_config.yaml b/labelme/config/default_config.yaml index 4af14f959..1d45970f9 100644 --- a/labelme/config/default_config.yaml +++ b/labelme/config/default_config.yaml @@ -100,3 +100,7 @@ shortcuts: add_point_to_edge: Ctrl+Shift+P edit_label: Ctrl+E toggle_keep_prev_mode: Ctrl+P + + show_all_polygons: G + hide_all_polygons: H + toggle_all_polygons: T diff --git a/labelme/translate/empty.ts b/labelme/translate/empty.ts index d871e7e32..4f608c115 100644 --- a/labelme/translate/empty.ts +++ b/labelme/translate/empty.ts @@ -332,6 +332,17 @@ Polygons Show all polygons + + + &Toggle +Polygons + + + + + Toggle all polygons + + &Tutorial diff --git a/labelme/translate/zh_CN.ts b/labelme/translate/zh_CN.ts index 45142a382..65a53fb4b 100644 --- a/labelme/translate/zh_CN.ts +++ b/labelme/translate/zh_CN.ts @@ -332,6 +332,17 @@ Polygons Show all polygons 显示所有多边形 + + + &Toggle +Polygons + 开关多边形(&S) + + + + Toggle all polygons + 开关所有多边形 + &Tutorial