This commit is contained in:
TzuTa Lin 2015-09-17 14:50:58 +08:00
parent 0f9cae650d
commit c40b0db7f2
4 changed files with 7 additions and 117 deletions

View File

@ -4,7 +4,7 @@ LabelImg is a graphical image annotation tool
It is written in Python and uses Qt for its graphical interface. It is written in Python and uses Qt for its graphical interface.
The annotation file will be saved as a XML file. The annotation format is Piscal VOC format, and the format is the same as [ImageNet](http://www.image-net.org/) The annotation file will be saved as a XML file. The annotation format is PASCAL VOC format, and the format is the same as [ImageNet](http://www.image-net.org/)
## Dependencies ## Dependencies
Requires at least [Python 2.6](http://www.python.org/getit/) and has been tested with [PyQt Requires at least [Python 2.6](http://www.python.org/getit/) and has been tested with [PyQt

View File

@ -3,7 +3,7 @@ import os.path
import numpy import numpy
import Image import Image
import sys import sys
from piscal_voc_writer import PiscalVocWriter from pascal_voc_writer import PascalVocWriter
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
class LabelFileError(Exception): class LabelFileError(Exception):
@ -59,7 +59,7 @@ class LabelFile(object):
imgFileName = os.path.basename(imagePath) imgFileName = os.path.basename(imagePath)
imgFileNameWithoutExt = os.path.splitext(imgFileName)[0] imgFileNameWithoutExt = os.path.splitext(imgFileName)[0]
imageShape = numpy.asarray(Image.open(imagePath)).shape imageShape = numpy.asarray(Image.open(imagePath)).shape
writer = PiscalVocWriter(imgFolderName, imgFileNameWithoutExt,\ writer = PascalVocWriter(imgFolderName, imgFileNameWithoutExt,\
imageShape, localImgPath=imagePath) imageShape, localImgPath=imagePath)
bSave = False bSave = False
for shape in shapes: for shape in shapes:

View File

@ -51,10 +51,10 @@ class MainWindow(QMainWindow, WindowMixin):
def __init__(self, filename=None): def __init__(self, filename=None):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.setWindowTitle(__appname__) self.setWindowTitle(__appname__)
# Save as Piscal voc xml # Save as Pascal voc xml
self.defaultSaveDir = None self.defaultSaveDir = None
self.usingPiscalVocFormat = True self.usingPascalVocFormat = True
if self.usingPiscalVocFormat: if self.usingPascalVocFormat:
LabelFile.suffix = '.xml' LabelFile.suffix = '.xml'
# For loading all image under a directory # For loading all image under a directory
self.mImgList = [] self.mImgList = []
@ -548,7 +548,7 @@ class MainWindow(QMainWindow, WindowMixin):
shapes = [format_shape(shape) for shape in self.canvas.shapes] shapes = [format_shape(shape) for shape in self.canvas.shapes]
try: try:
if self.usingPiscalVocFormat is True: if self.usingPascalVocFormat is True:
print 'savePascalVocFormat save to:' + filename print 'savePascalVocFormat save to:' + filename
lf.savePascalVocFormat(filename, shapes, unicode(self.filename), self.imageData, lf.savePascalVocFormat(filename, shapes, unicode(self.filename), self.imageData,
self.lineColor.getRgb(), self.fillColor.getRgb()) self.lineColor.getRgb(), self.fillColor.getRgb())

View File

@ -1,110 +0,0 @@
import sys
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement
from xml.dom import minidom
from lxml import etree
class PiscalVocWriter:
def __init__(self, foldername, filename, imgSize, databaseSrc='Unknown', localImgPath=None):
self.foldername = foldername
self.filename = filename
self.databaseSrc = databaseSrc
self.imgSize = imgSize
self.boxlist = []
self.localImgPath = localImgPath
def prettify(self, elem):
"""
Return a pretty-printed XML string for the Element.
"""
rough_string = ElementTree.tostring(elem,'utf8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
def genXML(self):
"""
Return XML root
"""
# Check conditions
if self.filename is None or \
self.foldername is None or \
self.imgSize is None or \
len(self.boxlist) <= 0:
return None
top = Element('annotation')
folder = SubElement(top,'folder')
folder.text = self.foldername
filename = SubElement(top,'filename')
filename.text = self.filename
localImgPath = SubElement(top,'path')
localImgPath.text = self.localImgPath
source = SubElement(top,'source')
database = SubElement(source,'database')
database.text = self.databaseSrc
size_part = SubElement(top,'size')
width = SubElement(size_part,'width')
height = SubElement(size_part,'height')
depth = SubElement(size_part,'depth')
width.text = str(self.imgSize[1])
height.text = str(self.imgSize[0])
if len(self.imgSize)==3:
depth.text = str(self.imgSize[2])
else:
depth.text = '1'
segmented = SubElement(top,'segmented')
segmented.text ='0'
return top
def addBndBox(self, xmin, ymin, xmax, ymax, name):
bndbox = {'xmin':xmin, 'ymin':ymin, 'xmax':xmax, 'ymax':ymax}
bndbox['name'] = name
self.boxlist.append(bndbox);
def appendObjects(self, top):
for each_object in self.boxlist:
object_item = SubElement(top,'object')
name = SubElement(object_item, 'name')
name.text = str(each_object['name'])
pose = SubElement(object_item, 'pose')
pose.text = "Unspecified"
truncated = SubElement(object_item, 'truncated')
truncated.text = "0"
difficult = SubElement(object_item, 'difficult')
difficult.text = "0"
bndbox = SubElement(object_item, 'bndbox')
xmin = SubElement(bndbox, 'xmin')
xmin.text = str(each_object['xmin'])
ymin = SubElement(bndbox, 'ymin')
ymin.text = str(each_object['ymin'])
xmax = SubElement(bndbox, 'xmax')
xmax.text = str(each_object['xmax'])
ymax = SubElement(bndbox, 'ymax')
ymax.text = str(each_object['ymax'])
def save(self, targetFile = None):
root = self.genXML()
self.appendObjects(root)
out_file = None
if targetFile is None:
out_file = open(self.filename + '.xml','w')
else:
out_file = open(targetFile, 'w')
out_file.write(self.prettify(root))
out_file.close()
"""
# Test
tmp = PiscalVocWriter('temp','test', (10,20,3))
tmp.addBndBox(10,10,20,30,'chair')
tmp.addBndBox(1,1,600,600,'car')
tmp.save()
"""