Skip to content
This repository was archived by the owner on Feb 29, 2024. It is now read-only.

Commit dd6f703

Browse files
custom flags
1 parent 8baba7e commit dd6f703

File tree

5 files changed

+95
-67
lines changed

5 files changed

+95
-67
lines changed

activate.bat

Lines changed: 0 additions & 2 deletions
This file was deleted.

build.bat

Lines changed: 0 additions & 6 deletions
This file was deleted.

labelImg.py

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,28 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa
134134
# Create Flag checkboxes list
135135
self.flagGroupBox = QGroupBox(self)
136136
self.flagGroupBox.setTitle('Flags')
137-
flagslayout = QVBoxLayout(self)
138-
self.flagGroupBox.setLayout(flagslayout)
139-
self.flagButtons = []
140137

141-
self.diffcButton = QCheckBox(getStr('useDifficult'))
142-
self.diffcButton.setChecked(False)
143-
# calling stateChanged is inappropriate!
144-
self.diffcButton.clicked.connect(self.btnstate)
145-
self.flagButtons.append(self.diffcButton)
138+
vbox = QVBoxLayout(self)
139+
self.flagslayout = QGridLayout(self)
140+
vbox.addLayout(self.flagslayout)
141+
142+
addflagLayout = QHBoxLayout(self)
143+
self.flaglineedit = QLineEdit()
144+
self.flaglineedit.setPlaceholderText('Flag name')
145+
self.flaglineedit.returnPressed.connect(self.addflag_button_pushed)
146+
addflagLayout.addWidget(self.flaglineedit, 9)
147+
self.addflag_button = QPushButton('↑')
148+
self.addflag_button.clicked.connect(self.addflag_button_pushed)
149+
addflagLayout.addWidget(self.addflag_button, 1)
150+
vbox.addLayout(addflagLayout)
146151

147-
self.truncButton = QCheckBox(getStr('useTruncated'))
148-
self.truncButton.setChecked(False)
149-
self.truncButton.clicked.connect(self.btnstate)
150-
self.flagButtons.append(self.truncButton)
152+
self.flagGroupBox.setLayout(vbox)
153+
# list of tuple(checkbox, x button)
154+
self.flagWidgets = []
155+
156+
# add difficult and truncated flag by default
157+
self.addFlags(getStr('useDifficult'))
158+
self.addFlags(getStr('useTruncated'))
151159

152160
# *
153161
# * dhzs 2017-12-2 add copy button
@@ -157,13 +165,9 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa
157165
self.copy_prev_button.clicked.connect(self.copyPreviousBoundingBoxes)
158166
listLayout.addWidget(self.copy_prev_button)
159167

160-
# add flag buttons to flagsGroupBox
161-
for flagbtn in self.flagButtons:
162-
flagslayout.addWidget(flagbtn)
163-
164168
# Add some of widgets to listLayout
165-
listLayout.addWidget(self.editButton)
166169
listLayout.addWidget(self.flagGroupBox)
170+
listLayout.addWidget(self.editButton)
167171
listLayout.addWidget(useDefaultLabelContainer)
168172

169173
# Create and add combobox for showing unique labels in group
@@ -756,8 +760,64 @@ def flags(self):
756760
"""
757761
return {flagbtn.text(): flagbtn.isChecked() for flagbtn in self.flagButtons}
758762

759-
def setFlagsChecked(self, flags):
760-
pass
763+
def addflag_button_pushed(self):
764+
# check whether the name is valid or not
765+
flagname = self.flaglineedit.text()
766+
if flagname == '':
767+
self.errorMessage('Invalid flag name', 'Input any texts!')
768+
return
769+
770+
if flagname in [c.text() for c in self.flagButtons]:
771+
self.errorMessage('Invalid flag name', 'Already exist!')
772+
return
773+
774+
self.addFlags(flagname)
775+
776+
def addFlags(self, name):
777+
column = len(self.flagWidgets)
778+
779+
newbtn = QCheckBox(name)
780+
newbtn.setChecked(False)
781+
# calling stateChanged is inappropriate!
782+
newbtn.clicked.connect(self.btnstate)
783+
self.flagslayout.addWidget(newbtn, *(column, 0))
784+
self.flagslayout.setColumnStretch(0, 9)
785+
786+
removebtn = QPushButton('X')
787+
widgets = (newbtn, removebtn)
788+
index = len(self.flagWidgets)
789+
removebtn.clicked.connect(lambda : self.removeFlags(index))
790+
self.flagslayout.addWidget(removebtn, *(column, 1))
791+
self.flagslayout.setColumnStretch(1, 1)
792+
self.flagWidgets.append(widgets)
793+
794+
795+
def removeFlags(self, index):
796+
# remove checkbox
797+
btn = self.flagWidgets[index][0]
798+
self.flagslayout.removeWidget(btn)
799+
800+
# remove x button
801+
removebtn = self.flagWidgets[index][1]
802+
self.flagslayout.removeWidget(removebtn)
803+
804+
btn.deleteLater()
805+
removebtn.deleteLater()
806+
del self.flagWidgets[index]
807+
808+
# update argument of removeFlags
809+
for i, removeBtn in enumerate(self.flagRemoveButtons):
810+
removebtn.clicked.connect(lambda : self.removeFlags(i))
811+
812+
@property
813+
def flagButtons(self):
814+
for widgets in self.flagWidgets:
815+
yield widgets[0]
816+
817+
@property
818+
def flagRemoveButtons(self):
819+
for widgets in self.flagWidgets:
820+
yield widgets[1]
761821

762822
# Add chris
763823
def btnstate(self, item= None):
@@ -826,6 +886,7 @@ def remLabel(self, shape):
826886

827887
def loadLabels(self, shapes):
828888
s = []
889+
flaglist = [btn.text() for btn in self.flagButtons]
829890
for label, points, line_color, fill_color, flags in shapes:
830891
shape = Shape(label=label)
831892
for x, y in points:
@@ -850,6 +911,11 @@ def loadLabels(self, shapes):
850911
else:
851912
shape.fill_color = generateColorByText(label)
852913

914+
# add flag if it doesn't exist
915+
for flagname in shape.flags.keys():
916+
if flagname not in flaglist:
917+
self.addFlags(flagname)
918+
853919
self.addLabel(shape)
854920
self.updateComboBox()
855921
self.canvas.loadShapes(s)

labelImg.spec

Lines changed: 0 additions & 33 deletions
This file was deleted.

libs/pascal_voc_io.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,18 @@ def parseXML(self):
156156
except KeyError:
157157
self.verified = False
158158

159+
noflag_list = ['name', 'pose', 'bndbox']
159160
for object_iter in xmltree.findall('object'):
160161
bndbox = object_iter.find("bndbox")
161162
label = object_iter.find('name').text
162163

163-
difficult = False
164-
if object_iter.find('difficult') is not None:
165-
difficult = bool(int(object_iter.find('difficult').text))
166-
truncated = False
167-
if object_iter.find('truncated') is not None:
168-
truncated = bool(int(object_iter.find('truncated').text))
169-
self.addShape(label, bndbox, flags={'difficult': difficult, 'truncated': truncated})
164+
flags = {'difficult': False, 'truncated': False}
165+
166+
for obj_node in object_iter:
167+
if obj_node.tag in noflag_list:
168+
continue
169+
val = bool(int(obj_node.text))
170+
flags[obj_node.tag] = val
171+
172+
self.addShape(label, bndbox, flags=flags)
170173
return True

0 commit comments

Comments
 (0)