2016-09-06 17:24:47 +08:00
|
|
|
# Copyright (c) 2016 Tzutalin
|
|
|
|
|
# Create by TzuTaLin <tzu.ta.lin@gmail.com>
|
|
|
|
|
|
2017-01-02 20:50:02 -05:00
|
|
|
try:
|
|
|
|
|
from PyQt5.QtGui import QImage
|
|
|
|
|
except ImportError:
|
|
|
|
|
from PyQt4.QtGui import QImage
|
|
|
|
|
|
2016-09-06 17:24:47 +08:00
|
|
|
from base64 import b64encode, b64decode
|
|
|
|
|
from pascal_voc_io import PascalVocWriter
|
|
|
|
|
import os.path
|
2015-09-17 10:37:20 +08:00
|
|
|
import sys
|
|
|
|
|
|
2017-02-28 11:50:15 +08:00
|
|
|
|
2015-09-17 10:37:20 +08:00
|
|
|
class LabelFileError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
2017-02-28 11:50:15 +08:00
|
|
|
|
2015-09-17 10:37:20 +08:00
|
|
|
class LabelFile(object):
|
|
|
|
|
# It might be changed as window creates
|
|
|
|
|
suffix = '.lif'
|
|
|
|
|
|
|
|
|
|
def __init__(self, filename=None):
|
|
|
|
|
self.shapes = ()
|
|
|
|
|
self.imagePath = None
|
|
|
|
|
self.imageData = None
|
2017-03-08 11:01:36 +08:00
|
|
|
self.verified = False
|
2015-09-17 10:37:20 +08:00
|
|
|
|
|
|
|
|
def savePascalVocFormat(self, filename, shapes, imagePath, imageData,
|
2017-02-28 11:50:15 +08:00
|
|
|
lineColor=None, fillColor=None, databaseSrc=None):
|
2015-09-17 10:37:20 +08:00
|
|
|
imgFolderPath = os.path.dirname(imagePath)
|
|
|
|
|
imgFolderName = os.path.split(imgFolderPath)[-1]
|
|
|
|
|
imgFileName = os.path.basename(imagePath)
|
|
|
|
|
imgFileNameWithoutExt = os.path.splitext(imgFileName)[0]
|
2016-09-06 17:24:47 +08:00
|
|
|
# Read from file path because self.imageData might be empty if saving to
|
|
|
|
|
# Pascal format
|
|
|
|
|
image = QImage()
|
|
|
|
|
image.load(imagePath)
|
2017-02-28 11:50:15 +08:00
|
|
|
imageShape = [image.height(), image.width(),
|
|
|
|
|
1 if image.isGrayscale() else 3]
|
|
|
|
|
writer = PascalVocWriter(imgFolderName, imgFileNameWithoutExt,
|
2015-09-17 10:37:20 +08:00
|
|
|
imageShape, localImgPath=imagePath)
|
2017-03-08 11:01:36 +08:00
|
|
|
writer.verified = self.verified
|
|
|
|
|
|
2015-09-17 10:37:20 +08:00
|
|
|
for shape in shapes:
|
|
|
|
|
points = shape['points']
|
|
|
|
|
label = shape['label']
|
2015-11-24 13:08:43 +08:00
|
|
|
bndbox = LabelFile.convertPoints2BndBox(points)
|
2015-09-17 10:37:20 +08:00
|
|
|
writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label)
|
|
|
|
|
|
2017-02-28 13:18:26 +08:00
|
|
|
writer.save(targetFile=filename)
|
2015-09-17 10:37:20 +08:00
|
|
|
return
|
|
|
|
|
|
2017-03-08 11:01:36 +08:00
|
|
|
def toggleVerify(self):
|
|
|
|
|
self.verified = not self.verified
|
|
|
|
|
|
2015-09-17 10:37:20 +08:00
|
|
|
@staticmethod
|
|
|
|
|
def isLabelFile(filename):
|
|
|
|
|
fileSuffix = os.path.splitext(filename)[1].lower()
|
|
|
|
|
return fileSuffix == LabelFile.suffix
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def convertPoints2BndBox(points):
|
2016-12-29 21:25:23 -05:00
|
|
|
xmin = float('inf')
|
|
|
|
|
ymin = float('inf')
|
|
|
|
|
xmax = float('-inf')
|
|
|
|
|
ymax = float('-inf')
|
2015-09-17 10:37:20 +08:00
|
|
|
for p in points:
|
|
|
|
|
x = p[0]
|
|
|
|
|
y = p[1]
|
2017-02-28 11:50:15 +08:00
|
|
|
xmin = min(x, xmin)
|
|
|
|
|
ymin = min(y, ymin)
|
|
|
|
|
xmax = max(x, xmax)
|
|
|
|
|
ymax = max(y, ymax)
|
2015-11-20 23:43:03 +08:00
|
|
|
|
|
|
|
|
# Martin Kersner, 2015/11/12
|
|
|
|
|
# 0-valued coordinates of BB caused an error while
|
|
|
|
|
# training faster-rcnn object detector.
|
2017-03-08 11:01:36 +08:00
|
|
|
if xmin < 1:
|
2015-11-20 23:43:03 +08:00
|
|
|
xmin = 1
|
|
|
|
|
|
2017-03-08 11:01:36 +08:00
|
|
|
if ymin < 1:
|
2015-11-20 23:43:03 +08:00
|
|
|
ymin = 1
|
|
|
|
|
|
2015-09-17 10:37:20 +08:00
|
|
|
return (int(xmin), int(ymin), int(xmax), int(ymax))
|