目標
打開一個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.