greenhouse/libs/labelFile.py

147 lines
5.1 KiB
Python
Raw Normal View History

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
2017-07-25 16:30:04 +08:00
from libs.pascal_voc_io import PascalVocWriter
2018-03-01 21:38:22 -06:00
from libs.yolo_io import YOLOWriter
2017-07-25 16:30:04 +08:00
from libs.pascal_voc_io import XML_EXT
2016-09-06 17:24:47 +08:00
import os.path
2015-09-17 10:37:20 +08:00
import sys
2015-09-17 10:37:20 +08:00
class LabelFileError(Exception):
pass
2015-09-17 10:37:20 +08:00
class LabelFile(object):
2017-05-31 09:34:51 +08:00
# It might be changed as window creates. By default, using XML ext
# suffix = '.lif'
suffix = XML_EXT
2015-09-17 10:37:20 +08:00
def __init__(self, filename=None):
self.shapes = ()
self.imagePath = None
self.imageData = None
self.verified = False
2015-09-17 10:37:20 +08:00
def savePascalVocFormat(self, filename, shapes, imagePath, imageData,
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)
2017-07-07 11:09:00 +08:00
#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)
imageShape = [image.height(), image.width(),
1 if image.isGrayscale() else 3]
2017-07-07 11:09:00 +08:00
writer = PascalVocWriter(imgFolderName, imgFileName,
2015-09-17 10:37:20 +08:00
imageShape, localImgPath=imagePath)
writer.verified = self.verified
2015-09-17 10:37:20 +08:00
for shape in shapes:
points = shape['points']
label = shape['label']
2017-05-31 09:34:51 +08:00
# Add Chris
2017-04-25 10:24:06 +02:00
difficult = int(shape['difficult'])
bndbox = LabelFile.convertPoints2BndBox(points)
2017-04-25 10:24:06 +02:00
writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label, difficult)
2015-09-17 10:37:20 +08:00
writer.save(targetFile=filename)
2015-09-17 10:37:20 +08:00
return
2018-03-01 21:38:22 -06:00
def saveYoloFormat(self, filename, shapes, imagePath, imageData, classList,
lineColor=None, fillColor=None, databaseSrc=None):
imgFolderPath = os.path.dirname(imagePath)
imgFolderName = os.path.split(imgFolderPath)[-1]
imgFileName = os.path.basename(imagePath)
#imgFileNameWithoutExt = os.path.splitext(imgFileName)[0]
# Read from file path because self.imageData might be empty if saving to
# Pascal format
image = QImage()
image.load(imagePath)
imageShape = [image.height(), image.width(),
1 if image.isGrayscale() else 3]
writer = YOLOWriter(imgFolderName, imgFileName,
imageShape, localImgPath=imagePath)
writer.verified = self.verified
for shape in shapes:
points = shape['points']
label = shape['label']
# Add Chris
difficult = int(shape['difficult'])
bndbox = LabelFile.convertPoints2BndBox(points)
writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label, difficult)
writer.save(targetFile=filename, classList=classList)
return
def toggleVerify(self):
self.verified = not self.verified
''' ttf is disable
def load(self, filename):
import json
with open(filename, 'rb') as f:
data = json.load(f)
imagePath = data['imagePath']
imageData = b64decode(data['imageData'])
lineColor = data['lineColor']
fillColor = data['fillColor']
shapes = ((s['label'], s['points'], s['line_color'], s['fill_color'])\
for s in data['shapes'])
# Only replace data after everything is loaded.
self.shapes = shapes
self.imagePath = imagePath
self.imageData = imageData
self.lineColor = lineColor
self.fillColor = fillColor
def save(self, filename, shapes, imagePath, imageData, lineColor=None, fillColor=None):
import json
with open(filename, 'wb') as f:
json.dump(dict(
shapes=shapes,
lineColor=lineColor, fillColor=fillColor,
imagePath=imagePath,
imageData=b64encode(imageData)),
f, ensure_ascii=True, indent=2)
'''
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):
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]
xmin = min(x, xmin)
ymin = min(y, ymin)
xmax = max(x, xmax)
ymax = max(y, ymax)
# Martin Kersner, 2015/11/12
# 0-valued coordinates of BB caused an error while
# training faster-rcnn object detector.
if xmin < 1:
xmin = 1
if ymin < 1:
ymin = 1
2015-09-17 10:37:20 +08:00
return (int(xmin), int(ymin), int(xmax), int(ymax))