|
@@ -3,7 +3,6 @@ import io
|
|
|
import os
|
|
|
import os.path as osp
|
|
|
import re
|
|
|
-import warnings
|
|
|
import webbrowser
|
|
|
|
|
|
import PIL.Image
|
|
@@ -19,6 +18,7 @@ from labelme import QT5
|
|
|
from labelme.config import get_config
|
|
|
from labelme.label_file import LabelFile
|
|
|
from labelme.label_file import LabelFileError
|
|
|
+from labelme import logger
|
|
|
from labelme.shape import DEFAULT_FILL_COLOR
|
|
|
from labelme.shape import DEFAULT_LINE_COLOR
|
|
|
from labelme.shape import Shape
|
|
@@ -68,7 +68,21 @@ class WindowMixin(object):
|
|
|
class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = 0, 1, 2
|
|
|
|
|
|
- def __init__(self, config=None, filename=None, output=None):
|
|
|
+ def __init__(
|
|
|
+ self,
|
|
|
+ config=None,
|
|
|
+ filename=None,
|
|
|
+ output=None,
|
|
|
+ output_file=None,
|
|
|
+ output_dir=None,
|
|
|
+ ):
|
|
|
+ if output is not None:
|
|
|
+ logger.warn(
|
|
|
+ 'argument output is deprecated, use output_file instead'
|
|
|
+ )
|
|
|
+ if output_file is None:
|
|
|
+ output_file = output
|
|
|
+
|
|
|
# see labelme/config/default_config.yaml for valid configuration
|
|
|
if config is None:
|
|
|
config = get_config()
|
|
@@ -507,15 +521,18 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
self.statusBar().showMessage('%s started.' % __appname__)
|
|
|
self.statusBar().show()
|
|
|
|
|
|
+ if output_file is not None and self._config['auto_save']:
|
|
|
+ logger.warn(
|
|
|
+ 'If `auto_save` argument is True, `output_file` argument '
|
|
|
+ 'is ignored and output filename is automatically '
|
|
|
+ 'set as IMAGE_BASENAME.json.'
|
|
|
+ )
|
|
|
+ self.output_file = output_file
|
|
|
+ self.output_dir = output_dir
|
|
|
+
|
|
|
# Application state.
|
|
|
self.image = QtGui.QImage()
|
|
|
self.imagePath = None
|
|
|
- if self._config['auto_save'] and output is not None:
|
|
|
- warnings.warn('If `auto_save` argument is True, `output` argument '
|
|
|
- 'is ignored and output filename is automatically '
|
|
|
- 'set as IMAGE_BASENAME.json.')
|
|
|
- self.labeling_once = output is not None
|
|
|
- self.output = output
|
|
|
self.recentFiles = []
|
|
|
self.maxRecent = 7
|
|
|
self.lineColor = None
|
|
@@ -595,6 +612,8 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
def setDirty(self):
|
|
|
if self._config['auto_save'] or self.actions.saveAuto.isChecked():
|
|
|
label_file = osp.splitext(self.imagePath)[0] + '.json'
|
|
|
+ if self.output_dir:
|
|
|
+ label_file = osp.join(self.output_dir, label_file)
|
|
|
self.saveLabels(label_file)
|
|
|
return
|
|
|
self.dirty = True
|
|
@@ -898,6 +917,8 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
imagePath = osp.relpath(
|
|
|
self.imagePath, osp.dirname(filename))
|
|
|
imageData = self.imageData if self._config['store_data'] else None
|
|
|
+ if not osp.exists(osp.dirname(filename)):
|
|
|
+ os.makedirs(osp.dirname(filename))
|
|
|
lf.save(
|
|
|
filename=filename,
|
|
|
shapes=shapes,
|
|
@@ -1053,6 +1074,8 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
# assumes same name, but json extension
|
|
|
self.status("Loading %s..." % osp.basename(str(filename)))
|
|
|
label_file = osp.splitext(filename)[0] + '.json'
|
|
|
+ if self.output_dir:
|
|
|
+ label_file = osp.join(self.output_dir, label_file)
|
|
|
if QtCore.QFile.exists(label_file) and \
|
|
|
LabelFile.isLabelFile(label_file):
|
|
|
try:
|
|
@@ -1255,8 +1278,9 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
if self.labelFile:
|
|
|
# DL20180323 - overwrite when in directory
|
|
|
self._saveFile(self.labelFile.filename)
|
|
|
- elif self.output:
|
|
|
- self._saveFile(self.output)
|
|
|
+ elif self.output_file:
|
|
|
+ self._saveFile(self.output_file)
|
|
|
+ self.close()
|
|
|
else:
|
|
|
self._saveFile(self.saveFileDialog())
|
|
|
|
|
@@ -1268,14 +1292,27 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
def saveFileDialog(self):
|
|
|
caption = '%s - Choose File' % __appname__
|
|
|
filters = 'Label files (*%s)' % LabelFile.suffix
|
|
|
- dlg = QtWidgets.QFileDialog(self, caption, self.currentPath(), filters)
|
|
|
+ if self.output_dir:
|
|
|
+ dlg = QtWidgets.QFileDialog(
|
|
|
+ self, caption, self.output_dir, filters
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ dlg = QtWidgets.QFileDialog(
|
|
|
+ self, caption, self.currentPath(), filters
|
|
|
+ )
|
|
|
dlg.setDefaultSuffix(LabelFile.suffix[1:])
|
|
|
dlg.setAcceptMode(QtWidgets.QFileDialog.AcceptSave)
|
|
|
dlg.setOption(QtWidgets.QFileDialog.DontConfirmOverwrite, False)
|
|
|
dlg.setOption(QtWidgets.QFileDialog.DontUseNativeDialog, False)
|
|
|
basename = osp.splitext(self.filename)[0]
|
|
|
- default_labelfile_name = osp.join(
|
|
|
- self.currentPath(), basename + LabelFile.suffix)
|
|
|
+ if self.output_dir:
|
|
|
+ default_labelfile_name = osp.join(
|
|
|
+ self.output_dir, basename + LabelFile.suffix
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ default_labelfile_name = osp.join(
|
|
|
+ self.currentPath(), basename + LabelFile.suffix
|
|
|
+ )
|
|
|
filename = dlg.getSaveFileName(
|
|
|
self, 'Choose File', default_labelfile_name,
|
|
|
'Label files (*%s)' % LabelFile.suffix)
|
|
@@ -1288,8 +1325,6 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
if filename and self.saveLabels(filename):
|
|
|
self.addRecentFile(filename)
|
|
|
self.setClean()
|
|
|
- if self.labeling_once:
|
|
|
- self.close()
|
|
|
|
|
|
def closeFile(self, _value=False):
|
|
|
if not self.mayContinue():
|
|
@@ -1429,6 +1464,8 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
|
|
|
if pattern and pattern not in filename:
|
|
|
continue
|
|
|
label_file = osp.splitext(filename)[0] + '.json'
|
|
|
+ if self.output_dir:
|
|
|
+ label_file = osp.join(self.output_dir, label_file)
|
|
|
item = QtWidgets.QListWidgetItem(filename)
|
|
|
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
|
|
if QtCore.QFile.exists(label_file) and \
|