目标
打开一个3ds Max的场景,设定好双目相机的位置以及自动关键帧(Auto Key),运行本脚本就能自动渲染并保存帧序列(可用于生成VR视频动画),当然,我们这里的目的是为了获取用于神经网络训练的数据集。
Talk is cheap, show me the code!
-- path to save rendering ouputs
root_path = "E:/Gits/Datasets/DCN/scene01"
main_path = root_path + "/picMain/"
aux_path = root_path + "/picAux/"
depth_path = root_path + "/depth/"
makeDir main_path all:true
makeDir aux_path all:true
makeDir depth_path all:true
-- set up rendering sequence
N = 16 -- how many frames to render
TIME_UNIT = 5 -- render every X second
START=101 -- the begin id, to keep digits length the same, begin from 101 is suggested
-- the size to save images
b = bitmap 800 600 -- the bitmap buffer to save, without this memory will increase
-- set up rendering timeout to speed up rendering
--RendererClass.classes as string
renderers.current = RendererClass.classes[7]() -- 8
"current render: " + (renderers.current as string)
vr = renderers.current
vr.max_render_time = 0.5 -- in minutes, 0.5 min ==30 seconds
--showproperties vr
-- setup vray to export depth maps
mgr = maxOps.GetCurRenderElementMgr() -- the cuurent render manager
mgr.removeallrenderelements() -- clean all previous rendering elements
mgr.addrenderelement (VRayZDepth elementname:(VRayZDepth as string)) -- add vraydepth element
zdepth=mgr.getRenderElement 0 -- get the vraydepth render element
zdepth.zdepth_min=0 -- set the nearest depth
zdepth.zdepth_max=30000 -- set the farest depth
zdepth.enabled = true -- enable this rendering element
zdepth.filterOn = true -- ensure this vraydepth element filter turned on
for fid = START to (START+N-1) do
(
-- render main camera with vray z-depth
render camera: $camMain to: b frame: ((fid-START)*TIME_UNIT)
b.filename = main_path +(fid as string) + "main.png"
save b
-- save depth map
--max render last
filename = depth_path + (fid as string) + "depth.png"
"current buffer channel numer: " + (vrayVFBGetNumChannels() as string)
vfbControl #setchannel 2
vfbControl #saveimage filename
-- render the aux camera
render camera: $camAux to: b frame: ((fid-START)*TIME_UNIT)
b.filename = aux_path + (fid as string) + "aux.png"
save b
)
close b
-- end
由于MAXScript语法高亮其实在Markdown中是不支持的,而恰好Lua脚本的语法和MAXScript很接近,因此我才用了Lua作为高亮提示。
结果
题外
- MAXScript确实非常好用,但我估计还是不如blender好,毕竟blender直接支持Python脚本!!!
- 对于AI从业者,MAXScript的学习成本比Blender的Python要高很多,主要是MAXScript的教程和资料太少,大多零散,语言类似lua,对于python用户来说不是很好上手。
- 要将深度图转化为对应的视差图还需要自己写python脚本,代码如下:
import numpy as np
import cv2
import glob
import os
import platform
def depth2disp(depth_u8:np.ndarray, d_min, d_max, fx, baseline, max_disp):
assert depth_u8.dtype == np.uint8
assert len(depth_u8.shape)==3
assert depth_u8.shape[2]==4
assert d_max > d_min
# refine the depth for sky from alpha channel
mask_alpha = depth_u8[:,:,3]
depth_32f = np.array(depth_u8[:,:,0], np.float32)
depth_32f[mask_alpha==0] = 0
d_min = max(d_min, 1e-6)
depth_32f = (255.0 - depth_32f)/255.0*(d_max - d_min) + d_min
disp_32f = (baseline*fx)/depth_32f
disp_32f = np.minimum(disp_32f, max_disp)
return np.uint8((disp_32f * 255.0 )/max_disp)
if __name__ == '__main__':
root_path = 'E:/Gits/Datasets/DCN/scene01'
if platform.system()=="Windows":
root_dir_win32 = root_path.replace('/', '\\\\')
os.system('md ' + root_dir_win32 + '\\\\disp')
#print('md ' + root_dir_win32 + '\\\\disp')
else:
os.system('mkdir -p ' + root_path + '/disp')
files = glob.glob(root_path + '/depth/*.png')
for i in range(len(files)):
im_depth = cv2.imread(files[i], -1)
im_disp = depth2disp(im_depth, 0, 30000, 355.096, 10.0, 4)
if platform.system()=="Windows":
cv2.imwrite(files[i].replace('depth\\', 'disp\\'), im_disp)
else:
cv2.imwrite(files[i].replace('depth/', 'disp/'), im_disp)
--- End.