-
Notifications
You must be signed in to change notification settings - Fork 3
/
svglabel.py
130 lines (112 loc) · 3.51 KB
/
svglabel.py
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
import base64
import json
import os.path
from PIL import Image
import svgpathtools as svg
# svg2json
def get_points(path, seg):
acc = []
close_shape = None
last_end = None
for p in path:
# close any open shapes before proceeding to the next point
if last_end and p.start != last_end:
# quickfix: labelme not recognizing exactly same points?
# https://github.com/wkentaro/labelme/issues/782
acc.append([last_end.real, last_end.imag + 0.001])
if close_shape:
acc.append(close_shape)
else:
close_shape = acc[-1]
# add the point
acc.append([p.start.real, p.start.imag])
# add any additional segment points
for i in range(seg):
val = float(i) / (seg + 1)
point = p.point(val)
acc.append([point.real, point.imag])
last_end = p.end
acc.append([last_end.real, last_end.imag + 0.001])
return acc
def make_obj(filename):
with open(filename, 'rb') as f: imageData = f.read()
imageData = base64.b64encode(imageData).decode('utf-8')
imagePath = os.path.relpath(filename)
return dict(
imagePath = imagePath,
imageData = imageData,
lineColor = [0,255,0,128],
fillColor = [255,0,0,128],
shapes = [],
)
def make_shape():
return dict(
label = '',
points = [],
line_color = None,
fill_color = None,
)
def svg2json(svgfile, imfile, outfile=None, labelfile=None, segments=10):
paths, attributes = svg.svg2paths(svgfile)
obj = make_obj(imfile)
if labelfile: label_lst = [l.rstrip('\n') for l in open(labelfile)]
for path, attr in zip(paths,attributes):
if labelfile:
label_name = attr['id'].split()[0]
if label_name not in label_lst:
raise Exception('No such label: {}'.format(label_name))
shape = make_shape()
shape['points'] = get_points(path,segments)
shape['label'] = attr['id']
obj['shapes'].append(shape)
obj['shapes'].reverse()
outfile = outfile or os.path.splitext(svgfile)[0] + '.json'
with open(outfile,'w') as f: json.dump(obj,f,indent=True)
print('Wrote to {}'.format(outfile))
# json2svg
def get_path(points):
acc = []
start = complex(*points[0])
points = points[1:] + points[:1]
for p in points:
end = complex(*p)
line = svg.Line(start, end)
acc.append(line)
start = end
return svg.Path(*acc)
def make_attributes(id):
return {
'id': id,
'fill': 'none',
'stroke': 'black',
'stroke-width': 1
}
def make_svg_attributes(imfile):
im = Image.open(imfile)
w,h = im.size
return dict(
width = w,
height = h,
viewBox = '0 0 {} {}'.format(w,h),
xmlns = 'http://www.w3.org/2000/svg',
)
def json2svg(jsonfile, outfile=None):
with open(jsonfile) as f: obj = json.load(f)
svg_attributes = make_svg_attributes(obj['imagePath'])
attributes = []
paths = []
for shape in obj['shapes']:
path = get_path(shape['points'])
attr = make_attributes(shape['label'])
paths.append(path)
attributes.append(attr)
paths.reverse()
attributes.reverse()
outfile = outfile or os.path.splitext(jsonfile)[0] + '.svg'
svg.wsvg(
paths=paths,
filename=outfile,
attributes=attributes,
svg_attributes=svg_attributes,
)
print('Wrote to {}'.format(outfile))