Implement verified feature

When pressing space, the user can flag the image as verified, a green background will appear.
This is used when creating a dataset automatically, the user can then through all the pictures and flag them instead of annotate them.
This commit is contained in:
Thibaut Mattio 2017-03-08 11:01:36 +08:00
parent ce853362e5
commit 3abd685a8d
4 changed files with 62 additions and 15 deletions

34
labelImg.py Executable file → Normal file
View File

@ -212,6 +212,9 @@ class MainWindow(QMainWindow, WindowMixin):
openPrevImg = action('&Prev Image', self.openPrevImg,
'a', 'prev', u'Open Prev')
verify = action('&Verify Image', self.verifyImg,
'space', 'verify', u'Verify Image')
save = action('&Save', self.saveFile,
'Ctrl+S', 'save', u'Save labels to file', enabled=False)
saveAs = action('&Save As', self.saveFileAs,
@ -353,7 +356,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.tools = self.toolbar('Tools')
self.actions.beginner = (
open, opendir, openNextImg, openPrevImg, save, None, create, copy, delete, None,
open, opendir, openNextImg, openPrevImg, verify, save, None, create, copy, delete, None,
zoomIn, zoom, zoomOut, fitWindow, fitWidth)
self.actions.advanced = (
@ -658,7 +661,9 @@ class MainWindow(QMainWindow, WindowMixin):
def saveLabels(self, annotationFilePath):
annotationFilePath = u(annotationFilePath)
lf = LabelFile()
if self.labelFile is None:
self.labelFile = LabelFile()
self.labelFile.verified = self.canvas.verified
def format_shape(s):
return dict(label=s.label,
@ -674,12 +679,11 @@ class MainWindow(QMainWindow, WindowMixin):
if self.usingPascalVocFormat is True:
print ('Img: ' + self.filePath +
' -> Its xml: ' + annotationFilePath)
lf.savePascalVocFormat(annotationFilePath, shapes, self.filePath, self.imageData,
self.labelFile.savePascalVocFormat(annotationFilePath, shapes, self.filePath, self.imageData,
self.lineColor.getRgb(), self.fillColor.getRgb())
else:
lf.save(annotationFilePath, shapes, self.filePath, self.imageData,
self.labelFile.save(annotationFilePath, shapes, self.filePath, self.imageData,
self.lineColor.getRgb(), self.fillColor.getRgb())
self.labelFile = lf
return True
except LabelFileError as e:
self.errorMessage(u'Error saving label data',
@ -829,7 +833,9 @@ class MainWindow(QMainWindow, WindowMixin):
xmlPath = os.path.join(self.defaultSaveDir, basename)
self.loadPascalXMLByFilename(xmlPath)
self.canvas.setFocus()
self.setWindowTitle('{} - {}'.format(__appname__, filePath))
self.canvas.setFocus(True)
return True
return False
@ -970,6 +976,21 @@ class MainWindow(QMainWindow, WindowMixin):
item = QListWidgetItem(imgPath)
self.fileListWidget.addItem(item)
def verifyImg(self, _value=False):
# Proceding next image without dialog if having any label
if self.filePath is not None:
try:
self.labelFile.toggleVerify()
except AttributeError:
# If the labelling file does not exist yet, create if and
# re-save it with the verified attribute.
self.saveFile()
self.labelFile.toggleVerify()
self.canvas.verified = self.labelFile.verified
self.paintCanvas()
self.saveFile()
def openPrevImg(self, _value=False):
if not self.mayContinue():
return
@ -1156,6 +1177,7 @@ class MainWindow(QMainWindow, WindowMixin):
tVocParseReader = PascalVocReader(xmlPath)
shapes = tVocParseReader.getShapes()
self.loadLabels(shapes)
self.canvas.verified = tVocParseReader.verified
class Settings(object):

View File

@ -59,6 +59,7 @@ class Canvas(QWidget):
# Set widget options.
self.setMouseTracking(True)
self.setFocusPolicy(Qt.WheelFocus)
self.verified = False
def enterEvent(self, ev):
self.overrideCursor(self._cursor)
@ -419,6 +420,16 @@ class Canvas(QWidget):
p.setBrush(brush)
p.drawRect(leftTop.x(), leftTop.y(), rectWidth, rectHeight)
self.setAutoFillBackground(True)
if self.verified:
pal = self.palette()
pal.setColor(self.backgroundRole(), QColor(184, 239, 38, 128))
self.setPalette(pal)
else:
pal = self.palette()
pal.setColor(self.backgroundRole(), QColor(232, 232, 232, 255))
self.setPalette(pal)
p.end()
def transformPos(self, point):

View File

@ -24,8 +24,7 @@ class LabelFile(object):
self.shapes = ()
self.imagePath = None
self.imageData = None
if filename is not None:
self.load(filename)
self.verified = False
def savePascalVocFormat(self, filename, shapes, imagePath, imageData,
lineColor=None, fillColor=None, databaseSrc=None):
@ -41,6 +40,8 @@ class LabelFile(object):
1 if image.isGrayscale() else 3]
writer = PascalVocWriter(imgFolderName, imgFileNameWithoutExt,
imageShape, localImgPath=imagePath)
writer.verified = self.verified
for shape in shapes:
points = shape['points']
label = shape['label']
@ -50,6 +51,9 @@ class LabelFile(object):
writer.save(targetFile=filename)
return
def toggleVerify(self):
self.verified = not self.verified
@staticmethod
def isLabelFile(filename):
fileSuffix = os.path.splitext(filename)[1].lower()
@ -72,10 +76,10 @@ class LabelFile(object):
# Martin Kersner, 2015/11/12
# 0-valued coordinates of BB caused an error while
# training faster-rcnn object detector.
if (xmin < 1):
if xmin < 1:
xmin = 1
if (ymin < 1):
if ymin < 1:
ymin = 1
return (int(xmin), int(ymin), int(xmax), int(ymax))

View File

@ -19,6 +19,7 @@ class PascalVocWriter:
self.imgSize = imgSize
self.boxlist = []
self.localImgPath = localImgPath
self.verified = False
def prettify(self, elem):
"""
@ -39,6 +40,8 @@ class PascalVocWriter:
return None
top = Element('annotation')
top.set('verified', 'yes' if self.verified else 'no')
folder = SubElement(top, 'folder')
folder.text = self.foldername
@ -119,6 +122,7 @@ class PascalVocReader:
# [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color]
self.shapes = []
self.filepath = filepath
self.verified = False
self.parseXML()
def getShapes(self):
@ -137,6 +141,12 @@ class PascalVocReader:
parser = etree.XMLParser(encoding='utf-8')
xmltree = ElementTree.parse(self.filepath, parser=parser).getroot()
filename = xmltree.find('filename').text
try:
verified = xmltree.attrib['verified']
if verified == 'yes':
self.verified = True
except AttributeError:
self.verified = False
for object_iter in xmltree.findall('object'):
bndbox = object_iter.find("bndbox")