-
Notifications
You must be signed in to change notification settings - Fork 17
/
render_mitsuba2_pc.py
211 lines (176 loc) · 6.37 KB
/
render_mitsuba2_pc.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
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import numpy as np
import sys, os, subprocess
import OpenEXR
import Imath
from PIL import Image
from plyfile import PlyData, PlyElement
PATH_TO_MITSUBA2 = "/home/tolga/Codes/mitsuba2/build/dist/mitsuba" # mitsuba exectuable
# replaced by command line arguments
# PATH_TO_NPY = 'pcl_ex.npy' # the tensor to load
# note that sampler is changed to 'independent' and the ldrfilm is changed to hdrfilm
xml_head = \
"""
<scene version="0.6.0">
<integrator type="path">
<integer name="maxDepth" value="-1"/>
</integrator>
<sensor type="perspective">
<float name="farClip" value="100"/>
<float name="nearClip" value="0.1"/>
<transform name="toWorld">
<lookat origin="3,3,3" target="0,0,0" up="0,0,1"/>
</transform>
<float name="fov" value="25"/>
<sampler type="independent">
<integer name="sampleCount" value="256"/>
</sampler>
<film type="hdrfilm">
<integer name="width" value="1920"/>
<integer name="height" value="1080"/>
<rfilter type="gaussian"/>
</film>
</sensor>
<bsdf type="roughplastic" id="surfaceMaterial">
<string name="distribution" value="ggx"/>
<float name="alpha" value="0.05"/>
<float name="intIOR" value="1.46"/>
<rgb name="diffuseReflectance" value="1,1,1"/> <!-- default 0.5 -->
</bsdf>
"""
# I also use a smaller point size
xml_ball_segment = \
"""
<shape type="sphere">
<float name="radius" value="0.015"/>
<transform name="toWorld">
<translate x="{}" y="{}" z="{}"/>
</transform>
<bsdf type="diffuse">
<rgb name="reflectance" value="{},{},{}"/>
</bsdf>
</shape>
"""
xml_tail = \
"""
<shape type="rectangle">
<ref name="bsdf" id="surfaceMaterial"/>
<transform name="toWorld">
<scale x="10" y="10" z="1"/>
<translate x="0" y="0" z="-0.5"/>
</transform>
</shape>
<shape type="rectangle">
<transform name="toWorld">
<scale x="10" y="10" z="1"/>
<lookat origin="-4,4,20" target="0,0,0" up="0,0,1"/>
</transform>
<emitter type="area">
<rgb name="radiance" value="6,6,6"/>
</emitter>
</shape>
</scene>
"""
def colormap(x, y, z):
vec = np.array([x, y, z])
vec = np.clip(vec, 0.001, 1.0)
norm = np.sqrt(np.sum(vec ** 2))
vec /= norm
return [vec[0], vec[1], vec[2]]
def standardize_bbox(pcl, points_per_object):
pt_indices = np.random.choice(pcl.shape[0], points_per_object, replace=False)
np.random.shuffle(pt_indices)
pcl = pcl[pt_indices] # n by 3
mins = np.amin(pcl, axis=0)
maxs = np.amax(pcl, axis=0)
center = (mins + maxs) / 2.
scale = np.amax(maxs - mins)
print("Center: {}, Scale: {}".format(center, scale))
result = ((pcl - center) / scale).astype(np.float32) # [-0.5, 0.5]
return result
# only for debugging reasons
def writeply(vertices, ply_file):
sv = np.shape(vertices)
points = []
for v in range(sv[0]):
vertex = vertices[v]
points.append("%f %f %f\n" % (vertex[0], vertex[1], vertex[2]))
print(np.shape(points))
file = open(ply_file, "w")
file.write('''ply
format ascii 1.0
element vertex %d
property float x
property float y
property float z
end_header
%s
''' % (len(vertices), "".join(points)))
file.close()
# as done in https://gist.github.com/drakeguan/6303065
def ConvertEXRToJPG(exrfile, jpgfile):
File = OpenEXR.InputFile(exrfile)
PixType = Imath.PixelType(Imath.PixelType.FLOAT)
DW = File.header()['dataWindow']
Size = (DW.max.x - DW.min.x + 1, DW.max.y - DW.min.y + 1)
rgb = [np.fromstring(File.channel(c, PixType), dtype=np.float32) for c in 'RGB']
for i in range(3):
rgb[i] = np.where(rgb[i] <= 0.0031308,
(rgb[i] * 12.92) * 255.0,
(1.055 * (rgb[i] ** (1.0 / 2.4)) - 0.055) * 255.0)
rgb8 = [Image.frombytes("F", Size, c.tostring()).convert("L") for c in rgb]
# rgb8 = [Image.fromarray(c.astype(int)) for c in rgb]
Image.merge("RGB", rgb8).save(jpgfile, "JPEG", quality=95)
def main(argv):
if (len(argv) < 2):
print('filename to npy/ply is not passed as argument. terminated.')
return
pathToFile = argv[1]
filename, file_extension = os.path.splitext(pathToFile)
folder = os.path.dirname(pathToFile)
filename = os.path.basename(pathToFile)
# for the moment supports npy and ply
if (file_extension == '.npy'):
pclTime = np.load(pathToFile)
pclTimeSize = np.shape(pclTime)
elif (file_extension == '.npz'):
pclTime = np.load(pathToFile)
pclTime = pclTime['pred']
pclTimeSize = np.shape(pclTime)
elif (file_extension == '.ply'):
ply = PlyData.read(pathToFile)
vertex = ply['vertex']
(x, y, z) = (vertex[t] for t in ('x', 'y', 'z'))
pclTime = np.column_stack((x, y, z))
else:
print('unsupported file format.')
return
if (len(np.shape(pclTime)) < 3):
pclTimeSize = [1, np.shape(pclTime)[0], np.shape(pclTime)[1]]
pclTime.resize(pclTimeSize)
for pcli in range(0, pclTimeSize[0]):
pcl = pclTime[pcli, :, :]
pcl = standardize_bbox(pcl, 2048)
pcl = pcl[:, [2, 0, 1]]
pcl[:, 0] *= -1
pcl[:, 2] += 0.0125
xml_segments = [xml_head]
for i in range(pcl.shape[0]):
color = colormap(pcl[i, 0] + 0.5, pcl[i, 1] + 0.5, pcl[i, 2] + 0.5 - 0.0125)
xml_segments.append(xml_ball_segment.format(pcl[i, 0], pcl[i, 1], pcl[i, 2], *color))
xml_segments.append(xml_tail)
xml_content = str.join('', xml_segments)
xmlFile = ("%s/%s_%02d.xml" % (folder, filename, pcli))
with open(xmlFile, 'w') as f:
f.write(xml_content)
f.close()
exrFile = ("%s/%s_%02d.exr" % (folder, filename, pcli))
if (not os.path.exists(exrFile)):
print(['Running Mitsuba, writing to: ', xmlFile])
subprocess.run([PATH_TO_MITSUBA2, xmlFile])
else:
print('skipping rendering because the EXR file already exists')
png = ("%s/%s_%02d.jpg" % (folder, filename, pcli))
print(['Converting EXR to JPG...'])
ConvertEXRToJPG(exrFile, png)
if __name__ == "__main__":
main(sys.argv)