-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlabel_file.py
More file actions
183 lines (168 loc) · 5.76 KB
/
label_file.py
File metadata and controls
183 lines (168 loc) · 5.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import base64
import io
import json
import os.path as osp
import PIL.Image
from app import __version__
import glog as log
from app import PY2
from app import QT4
import utils
class LabelFileError(Exception):
pass
class LabelFile(object):
suffix = '.json'
def __init__(self, filename=None):
self.shapes = ()
self.imagePath = None
self.imageData = None
if filename is not None:
self.load(filename)
self.filename = filename
@staticmethod
def load_image_file(filename):
try:
image_pil = PIL.Image.open(filename)
except IOError:
log.error('Failed opening image file: {}'.format(filename))
return
# copy same white image to map
img_w, img_h = image_pil.size
if img_w > img_h:
background = PIL.Image.new('RGB', (img_w, img_h * 2), (255, 255, 255))
alter = (img_w, img_h,0,1)
else:
background = PIL.Image.new('RGB', (img_w * 2, img_h), (255, 255, 255))
alter = (img_w, img_h,1,0)
offset = (0, 0)
background.paste(image_pil, offset)
image_pil = background
# apply orientation to image according to exif
image_pil = utils.apply_exif_orientation(image_pil)
with io.BytesIO() as f:
ext = osp.splitext(filename)[1].lower()
if PY2 and QT4:
format = 'PNG'
elif ext in ['.jpg', '.jpeg']:
format = 'JPEG'
else:
format = 'PNG'
image_pil.save(f, format=format)
f.seek(0)
return f.read(),alter
def load(self, filename):
keys = [
'imageData',
'imagePath',
'lineColor',
'fillColor',
'shapes', # polygonal annotations
'flags', # image level flags
'imageHeight',
'imageWidth',
]
try:
with open(filename, 'rb' if PY2 else 'r', encoding='utf-8') as f:
data = json.load(f)
if data['imageData'] is not None:
imageData = base64.b64decode(data['imageData'])
if PY2 and QT4:
imageData = utils.img_data_to_png_data(imageData)
else:
# relative path from label file to relative path from cwd
imagePath = osp.join(osp.dirname(filename), data['imagePath'])
imageData = self.load_image_file(imagePath)
flags = data.get('flags')
imagePath = data['imagePath']
self._check_image_height_and_width(
base64.b64encode(imageData).decode('utf-8'),
data.get('imageHeight'),
data.get('imageWidth'),
)
lineColor = data['lineColor']
fillColor = data['fillColor']
shapes = (
(
s['label'],
s['points'],
s['line_color'],
s['fill_color'],
s.get('shape_type', 'polygon'),
)
for s in data['shapes']
)
except Exception as e:
raise LabelFileError(e)
otherData = {}
for key, value in data.items():
if key not in keys:
otherData[key] = value
# Only replace data after everything is loaded.
self.flags = flags
self.shapes = shapes
self.imagePath = imagePath
self.imageData = imageData
self.lineColor = lineColor
self.fillColor = fillColor
self.filename = filename
self.otherData = otherData
@staticmethod
def _check_image_height_and_width(imageData, imageHeight, imageWidth):
img_arr = utils.img_b64_to_arr(imageData)
if imageHeight is not None and img_arr.shape[0] != imageHeight:
log.error(
'imageHeight does not match with imageData or imagePath, '
'so getting imageHeight from actual image.'
)
imageHeight = img_arr.shape[0]
if imageWidth is not None and img_arr.shape[1] != imageWidth:
log.error(
'imageWidth does not match with imageData or imagePath, '
'so getting imageWidth from actual image.'
)
imageWidth = img_arr.shape[1]
return imageHeight, imageWidth
def save(
self,
filename,
shapes,
imagePath,
imageHeight,
imageWidth,
imageData=None,
lineColor=None,
fillColor=None,
otherData=None,
flags=None,
):
if imageData is not None:
imageData = base64.b64encode(imageData).decode('utf-8')
imageHeight, imageWidth = self._check_image_height_and_width(
imageData, imageHeight, imageWidth
)
if otherData is None:
otherData = {}
if flags is None:
flags = {}
data = dict(
version=__version__,
flags=flags,
shapes=shapes,
lineColor=lineColor,
fillColor=fillColor,
imagePath=imagePath,
imageData=imageData,
imageHeight=imageHeight,
imageWidth=imageWidth,
)
for key, value in otherData.items():
data[key] = value
try:
with open(filename, 'wb' if PY2 else 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
self.filename = filename
except Exception as e:
raise LabelFileError(e)
@staticmethod
def is_label_file(filename):
return osp.splitext(filename)[1].lower() == LabelFile.suffix