Skip to content

Commit f643baf

Browse files
committed
Add image level flag annotation
1 parent abbe9c1 commit f643baf

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

labelme/app.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ def __init__(self, config=None, filename=None, output=None):
165165
self.labelListContainer = QtWidgets.QWidget()
166166
self.labelListContainer.setLayout(listLayout)
167167

168+
self.flag_dock = self.flag_widget = None
169+
self.flag_dock = QtWidgets.QDockWidget('Flags', self)
170+
self.flag_dock.setObjectName('Flags')
171+
self.flag_widget = QtWidgets.QListWidget()
172+
if config['flags']:
173+
self.loadFlags({k: False for k in config['flags']})
174+
self.flag_dock.setWidget(self.flag_widget)
175+
self.flag_widget.itemChanged.connect(self.setDirty)
176+
168177
self.uniqLabelList = EscapableQListWidget()
169178
self.uniqLabelList.setToolTip(
170179
"Select label to start annotating for it. "
@@ -214,6 +223,7 @@ def __init__(self, config=None, filename=None, output=None):
214223

215224
self.setCentralWidget(scrollArea)
216225

226+
self.addDockWidget(Qt.RightDockWidgetArea, self.flag_dock)
217227
self.addDockWidget(Qt.RightDockWidgetArea, self.labelsdock)
218228
self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
219229
self.addDockWidget(Qt.RightDockWidgetArea, self.filedock)
@@ -686,6 +696,14 @@ def loadLabels(self, shapes):
686696
shape.fill_color = QtGui.QColor(*fill_color)
687697
self.loadShapes(s)
688698

699+
def loadFlags(self, flags):
700+
self.flag_widget.clear()
701+
for key, flag in flags.items():
702+
item = QtWidgets.QListWidgetItem(key)
703+
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
704+
item.setCheckState(Qt.Checked if flag else Qt.Unchecked)
705+
self.flag_widget.addItem(item)
706+
689707
def saveLabels(self, filename):
690708
lf = LabelFile()
691709

@@ -698,13 +716,26 @@ def format_shape(s):
698716
points=[(p.x(), p.y()) for p in s.points])
699717

700718
shapes = [format_shape(shape) for shape in self.labelList.shapes]
719+
flags = {}
720+
for i in range(len(self.flag_widget)):
721+
item = self.flag_widget.item(i)
722+
key = item.text()
723+
flag = item.checkState() == Qt.Checked
724+
flags[key] = flag
701725
try:
702726
imagePath = os.path.relpath(
703727
self.imagePath, os.path.dirname(filename))
704728
imageData = self.imageData if self._config['store_data'] else None
705-
lf.save(filename, shapes, imagePath, imageData,
706-
self.lineColor.getRgb(), self.fillColor.getRgb(),
707-
self.otherData)
729+
lf.save(
730+
filename=filename,
731+
shapes=shapes,
732+
imagePath=imagePath,
733+
imageData=imageData,
734+
lineColor=self.lineColor.getRgb(),
735+
fillColor=self.fillColor.getRgb(),
736+
otherData=self.otherData,
737+
flags=flags,
738+
)
708739
self.labelFile = lf
709740
# disable allows next and previous image to proceed
710741
# self.filename = filename
@@ -880,6 +911,8 @@ def loadFile(self, filename=None):
880911
self.canvas.loadPixmap(QtGui.QPixmap.fromImage(image))
881912
if self.labelFile:
882913
self.loadLabels(self.labelFile.shapes)
914+
if self.labelFile.flags is not None:
915+
self.loadFlags(self.labelFile.flags)
883916
self.setClean()
884917
self.canvas.setEnabled(True)
885918
self.adjustScale(initial=True)
@@ -1243,16 +1276,9 @@ def main():
12431276
output = config_from_args.pop('output')
12441277
config_file = config_from_args.pop('config_file')
12451278
# drop the default config
1246-
if not config_from_args['auto_save']:
1247-
config_from_args.pop('auto_save')
1248-
if config_from_args['store_data']:
1249-
config_from_args.pop('store_data')
1250-
if not config_from_args['labels']:
1251-
config_from_args.pop('labels')
1252-
if not config_from_args['sort_labels']:
1253-
config_from_args.pop('sort_labels')
1254-
if not config_from_args['validate_label']:
1255-
config_from_args.pop('validate_label')
1279+
for k, v in list(config_from_args.items()):
1280+
if v is None:
1281+
config_from_args.pop(k)
12561282
config = get_config(config_from_args, config_file)
12571283

12581284
app = QtWidgets.QApplication(sys.argv)

labelme/config/default_config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
auto_save: false
22
store_data: true
33

4+
flags: null
45
labels: null
56
sort_labels: true
67
validate_label: null

labelme/labelFile.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ def __init__(self, filename=None):
2424
self.filename = filename
2525

2626
def load(self, filename):
27-
keys = ['imageData', 'imagePath', 'lineColor', 'fillColor', 'shapes']
27+
keys = [
28+
'imageData',
29+
'imagePath',
30+
'lineColor',
31+
'fillColor',
32+
'shapes', # polygonal annotations
33+
'flags', # image level flags
34+
]
2835
try:
2936
with open(filename, 'rb' if PY2 else 'r') as f:
3037
data = json.load(f)
@@ -36,6 +43,7 @@ def load(self, filename):
3643
data['imagePath'])
3744
with open(imagePath, 'rb') as f:
3845
imageData = f.read()
46+
flags = data.get('flags')
3947
imagePath = data['imagePath']
4048
lineColor = data['lineColor']
4149
fillColor = data['fillColor']
@@ -52,6 +60,7 @@ def load(self, filename):
5260
otherData[key] = value
5361

5462
# Only replace data after everything is loaded.
63+
self.flags = flags
5564
self.shapes = shapes
5665
self.imagePath = imagePath
5766
self.imageData = imageData
@@ -61,12 +70,16 @@ def load(self, filename):
6170
self.otherData = otherData
6271

6372
def save(self, filename, shapes, imagePath, imageData=None,
64-
lineColor=None, fillColor=None, otherData=None):
73+
lineColor=None, fillColor=None, otherData=None,
74+
flags=None):
6575
if imageData is not None:
6676
imageData = base64.b64encode(imageData).decode('utf-8')
6777
if otherData is None:
6878
otherData = {}
79+
if flags is None:
80+
flags = []
6981
data = dict(
82+
flags=flags,
7083
shapes=shapes,
7184
lineColor=lineColor,
7285
fillColor=fillColor,

0 commit comments

Comments
 (0)