add render script
This commit is contained in:
parent
dcbc48cf33
commit
e1ccb44926
69
apps/postprocess/render.py
Normal file
69
apps/postprocess/render.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
'''
|
||||||
|
@ Date: 2022-04-14 14:05:50
|
||||||
|
@ Author: Qing Shuai
|
||||||
|
@ Mail: s_q@zju.edu.cn
|
||||||
|
@ LastEditors: Qing Shuai
|
||||||
|
@ LastEditTime: 2022-05-19 23:09:57
|
||||||
|
@ FilePath: /EasyMocapPublic/apps/postprocess/render.py
|
||||||
|
'''
|
||||||
|
from os.path import join
|
||||||
|
from easymocap.config import Config, load_object
|
||||||
|
from easymocap.config.baseconfig import load_config_from_index, load_object_from_cmd
|
||||||
|
from easymocap.mytools.debug_utils import mywarn, log, myerror
|
||||||
|
from tqdm import tqdm
|
||||||
|
from easymocap.mytools import Timer
|
||||||
|
|
||||||
|
index = Config.load('config/render_index.yml', [])
|
||||||
|
|
||||||
|
def vis(cfg):
|
||||||
|
# 读入模型
|
||||||
|
body_model = load_object_from_cmd(args.model, [])
|
||||||
|
# # 读入参数
|
||||||
|
results = load_object(cfg.result_module, cfg.result_args, body_model=body_model)
|
||||||
|
inputs = load_object(cfg.input_module, cfg.input_args)
|
||||||
|
outputs = load_object(cfg.output_module, cfg.output_args)
|
||||||
|
silent = True
|
||||||
|
for nf in tqdm(range(cfg.ranges[0], min(cfg.ranges[1], len(results)), cfg.ranges[2]), desc='vis'):
|
||||||
|
with Timer('result', silent):
|
||||||
|
basename, result = results[nf]
|
||||||
|
with Timer('inputs', silent):
|
||||||
|
images, cameras = inputs(basename)
|
||||||
|
with Timer('outputs', silent):
|
||||||
|
outputs(images, result, cameras, basename)
|
||||||
|
if cfg.make_video:
|
||||||
|
video = load_object(cfg.video_module, cfg.video_args)
|
||||||
|
video.make_video(cfg.output_args.out)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('path', type=str)
|
||||||
|
parser.add_argument('--mode', type=str, default='mesh')
|
||||||
|
parser.add_argument('--ranges', type=int, default=[], nargs=3)
|
||||||
|
parser.add_argument('--subs', type=str, default=[], nargs="+")
|
||||||
|
parser.add_argument('--exp', type=str, default=None)
|
||||||
|
parser.add_argument('--model', type=str, default=None)
|
||||||
|
parser.add_argument('--result', type=str, default=None)
|
||||||
|
parser.add_argument('--output', type=str, default=None)
|
||||||
|
parser.add_argument('--debug', action='store_true')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
config, ori = load_config_from_index(index, args.mode)
|
||||||
|
mode = ori.alias
|
||||||
|
if args.model is None:
|
||||||
|
args.model = join(args.path, args.exp, 'cfg_model.yml')
|
||||||
|
mywarn('[vis] args.model is not specified, use {}'.format(args.model))
|
||||||
|
if args.result is None:
|
||||||
|
args.result = join(args.path, args.exp, 'smpl')
|
||||||
|
mywarn('[vis] args.result is not specified, use {}'.format(args.result))
|
||||||
|
if args.output is None:
|
||||||
|
args.output = join(args.path, args.exp, mode)
|
||||||
|
mywarn('[vis] args.output is not specified, use {}'.format(args.output))
|
||||||
|
if len(args.subs) != 0:
|
||||||
|
config.input_args.subs = args.subs
|
||||||
|
if len(args.ranges) != 0:
|
||||||
|
config.ranges = args.ranges
|
||||||
|
config.input_args.path = args.path
|
||||||
|
config.result_args.path = args.result
|
||||||
|
config.output_args.out = args.output
|
||||||
|
vis(config)
|
9
config/render/input_mv.yml
Normal file
9
config/render/input_mv.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
input_module: 'easymocap.visualize.render_base.Images'
|
||||||
|
input_args:
|
||||||
|
path: none
|
||||||
|
subs: []
|
||||||
|
image_args:
|
||||||
|
scale: 1.
|
||||||
|
undis: True
|
||||||
|
tgt_shape: [-1, -1]
|
||||||
|
ext: .jpg
|
5
config/render/output_image.yml
Normal file
5
config/render/output_image.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
output_module: easymocap.visualize.render_base.MIOutputs
|
||||||
|
output_args:
|
||||||
|
out: none
|
||||||
|
mode: image
|
||||||
|
backend: pyrender
|
5
config/render/result_smpl.yml
Normal file
5
config/render/result_smpl.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ranges: [0, 99999, 1]
|
||||||
|
result_module: easymocap.visualize.render_base.Results
|
||||||
|
result_args:
|
||||||
|
path: none
|
||||||
|
rend_type: mesh
|
8
config/render/video.yml
Normal file
8
config/render/video.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
make_video: True
|
||||||
|
|
||||||
|
video_module: easymocap.visualize.ffmpeg_wrapper.VideoMaker
|
||||||
|
video_args:
|
||||||
|
restart: True
|
||||||
|
remove_images: False
|
||||||
|
fps_in: 50
|
||||||
|
fps_out: 50
|
60
config/render_index.yml
Normal file
60
config/render_index.yml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
skel:
|
||||||
|
alias: skel
|
||||||
|
result: config/render/result_skel.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_repro.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
mesh:
|
||||||
|
alias: mesh
|
||||||
|
result: config/render/result_smpl.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_image.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
ground+skel:
|
||||||
|
alias: ground
|
||||||
|
result: config/render/result_skel.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_ground.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
ground+mesh:
|
||||||
|
alias: ground
|
||||||
|
result: config/render/result_smpl.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_ground.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
ground+mesh+object:
|
||||||
|
alias: ground
|
||||||
|
result: config/render/result_smpl_object.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_ground.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
mesh-view:
|
||||||
|
alias: mesh
|
||||||
|
result: config/render/result_smpl.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_image.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
opts: [output_args.merge, False]
|
||||||
|
mask:
|
||||||
|
exp: mesh
|
||||||
|
alias: mask
|
||||||
|
opts: [output_args.mode, mask]
|
||||||
|
depth:
|
||||||
|
exp: mesh
|
||||||
|
alias: depth
|
||||||
|
opts: [output_args.mode, depth, output_args.merge, False]
|
||||||
|
mimoinstance:
|
||||||
|
alias: instance
|
||||||
|
result: config/render/result_smpl.yml
|
||||||
|
images: config/render/input_mv.yml
|
||||||
|
output: config/render/output_image.yml
|
||||||
|
video: config/render/video.yml
|
||||||
|
opts: [output_args.mode, instance-mask]
|
||||||
|
instance-d0.05:
|
||||||
|
alias: instance
|
||||||
|
exp: mimoinstance
|
||||||
|
opts: [result_args.operation, dilation:0.05]
|
||||||
|
instance-d0.1:
|
||||||
|
alias: instance
|
||||||
|
exp: mimoinstance
|
||||||
|
opts: [result_args.operation, dilation:0.1]
|
320
easymocap/visualize/render_base.py
Normal file
320
easymocap/visualize/render_base.py
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
'''
|
||||||
|
@ Date: 2021-11-22 15:16:14
|
||||||
|
@ Author: Qing Shuai
|
||||||
|
@ LastEditors: Qing Shuai
|
||||||
|
@ LastEditTime: 2022-09-28 21:40:17
|
||||||
|
@ FilePath: /EasyMocapPublic/easymocap/visualize/render_base.py
|
||||||
|
'''
|
||||||
|
from glob import glob
|
||||||
|
from os.path import join
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from ..mytools.file_utils import read_json
|
||||||
|
from ..mytools.debug_utils import log
|
||||||
|
from ..mytools.reader import read_keypoints3d, read_smpl
|
||||||
|
import os
|
||||||
|
from ..mytools.camera_utils import read_cameras, Undistort
|
||||||
|
import cv2
|
||||||
|
from ..mytools.vis_base import merge, plot_keypoints_auto
|
||||||
|
from ..config.baseconfig import load_object
|
||||||
|
from .geometry import load_sphere
|
||||||
|
|
||||||
|
def imwrite(imgname, img):
|
||||||
|
if not os.path.exists(os.path.dirname(imgname)):
|
||||||
|
os.makedirs(os.path.dirname(imgname))
|
||||||
|
if img.shape[0] % 2 == 1 or img.shape[1] % 2 == 1:
|
||||||
|
img = cv2.resize(img, (img.shape[1]//2*2, img.shape[0]//2*2))
|
||||||
|
cv2.imwrite(imgname, img)
|
||||||
|
|
||||||
|
def compute_normals(vertices, faces):
|
||||||
|
normal = np.zeros_like(vertices)
|
||||||
|
|
||||||
|
# compute normal per triangle
|
||||||
|
normal_faces = np.cross(vertices[faces[:,1]] - vertices[faces[:,0]], vertices[faces[:,2]] - vertices[faces[:,0]])
|
||||||
|
|
||||||
|
# sum normals at vtx
|
||||||
|
normal[faces[:, 0]] += normal_faces[:]
|
||||||
|
normal[faces[:, 1]] += normal_faces[:]
|
||||||
|
normal[faces[:, 2]] += normal_faces[:]
|
||||||
|
|
||||||
|
# compute norms
|
||||||
|
normal = normal / np.linalg.norm(normal, axis=-1, keepdims=True)
|
||||||
|
|
||||||
|
return normal
|
||||||
|
|
||||||
|
def get_dilation_of_mesh(delta):
|
||||||
|
def func(info):
|
||||||
|
vertices = info['vertices']
|
||||||
|
normals = compute_normals(info['vertices'], info['faces'])
|
||||||
|
vertices += delta * normals
|
||||||
|
return info
|
||||||
|
return func
|
||||||
|
|
||||||
|
class Results:
|
||||||
|
def __init__(self, body_model, path, rend_type,
|
||||||
|
operation='none') -> None:
|
||||||
|
self.path = path
|
||||||
|
self.body_model = body_model
|
||||||
|
self.skelnames = sorted(glob(join(path, '*.json')))
|
||||||
|
self.ismulti = False
|
||||||
|
if len(self.skelnames) == 0:
|
||||||
|
# 尝试找多视角的结果
|
||||||
|
subs = sorted(os.listdir(path))
|
||||||
|
assert len(subs) > 0, path
|
||||||
|
self.ismulti = True
|
||||||
|
self.subs = subs
|
||||||
|
self.skelnames = {}
|
||||||
|
for sub in subs:
|
||||||
|
skelnames = sorted(glob(join(path, sub, '*.json')))
|
||||||
|
self.skelnames[sub] = skelnames
|
||||||
|
self.rend_type = rend_type
|
||||||
|
self.read_func = {'skel': read_keypoints3d, 'mesh': read_smpl}[rend_type]
|
||||||
|
if operation.startswith('dilation'):
|
||||||
|
# TODO: 暂时直接解析
|
||||||
|
opfunc = get_dilation_of_mesh(float(operation.replace('dilation:', '')))
|
||||||
|
else:
|
||||||
|
opfunc = lambda x:x
|
||||||
|
self.operation = opfunc
|
||||||
|
|
||||||
|
def process(self, info):
|
||||||
|
return info
|
||||||
|
|
||||||
|
def read(self, skelname):
|
||||||
|
results = self.read_func(skelname)
|
||||||
|
render_data = {}
|
||||||
|
trans = np.array([[0., 0., 0., 0.]])
|
||||||
|
for info in results:
|
||||||
|
info['vertices'] = self.body_model(return_verts=True, return_tensor=False, **info)[0]
|
||||||
|
info['keypoints3d'] = self.body_model(return_verts=False, return_tensor=False, **info)[0]
|
||||||
|
info['vertices'] += trans[:, :3]
|
||||||
|
info['faces'] = self.body_model.faces
|
||||||
|
d = self.operation(info)
|
||||||
|
render_data[d['id']] = {
|
||||||
|
'vertices': d['vertices'], 'keypoints3d': d['keypoints3d'],
|
||||||
|
'faces': info['faces'],
|
||||||
|
'vid': d['id'], 'name': 'human_{}'.format(d['id'])}
|
||||||
|
if self.rend_type == 'skel':
|
||||||
|
render_data[d['id']]['smooth'] = False
|
||||||
|
return render_data
|
||||||
|
|
||||||
|
def get_multi(self, index):
|
||||||
|
datas = {}
|
||||||
|
for sub in self.subs:
|
||||||
|
skelname = self.skelnames[sub][index]
|
||||||
|
basename = os.path.basename(skelname).replace('.json', '')
|
||||||
|
render_data = self.read(skelname)
|
||||||
|
datas[sub] = render_data
|
||||||
|
return basename, datas
|
||||||
|
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if self.ismulti:
|
||||||
|
return self.get_multi(index)
|
||||||
|
else:
|
||||||
|
skelname = self.skelnames[index]
|
||||||
|
basename = os.path.basename(skelname).replace('.json', '')
|
||||||
|
return basename, self.read(skelname)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
if self.ismulti:
|
||||||
|
return len(self.skelnames[self.subs[0]])
|
||||||
|
else:
|
||||||
|
return len(self.skelnames)
|
||||||
|
|
||||||
|
class ResultsObjects(Results):
|
||||||
|
def __init__(self, object,**kwargs) -> None:
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.object = object
|
||||||
|
|
||||||
|
def __getitem__(self, index):
|
||||||
|
basename, datas = super().__getitem__(index)
|
||||||
|
objectname = join(self.path, '..', '..', self.object, basename+'.json')
|
||||||
|
objects = read_json(objectname)
|
||||||
|
ret_objects = {}
|
||||||
|
for obj in objects:
|
||||||
|
pid = obj['id']
|
||||||
|
vertices, faces = load_sphere()
|
||||||
|
vertices *= 0.12
|
||||||
|
vertices += np.array(obj['keypoints3d'])[:, :3]
|
||||||
|
ret_objects[1000+pid] = {
|
||||||
|
'vertices': vertices,
|
||||||
|
'faces': faces,
|
||||||
|
'vid': pid,
|
||||||
|
'name': 'object_{}'.format(pid)
|
||||||
|
}
|
||||||
|
if self.ismulti:
|
||||||
|
for key, data in datas.items():
|
||||||
|
data.update(ret_objects)
|
||||||
|
else:
|
||||||
|
datas.update(ret_objects)
|
||||||
|
return basename, datas
|
||||||
|
|
||||||
|
class Images:
|
||||||
|
def __init__(self, path, subs, image_args) -> None:
|
||||||
|
if path == 'none':
|
||||||
|
self.images = path
|
||||||
|
# no need for images
|
||||||
|
assert len(subs) > 0, '{} must non-empty'.format(subs)
|
||||||
|
else:
|
||||||
|
self.images = join(path, 'images')
|
||||||
|
if len(subs) == 0:
|
||||||
|
subs = sorted(os.listdir(self.images))
|
||||||
|
if subs[0].isdigit():
|
||||||
|
subs.sort(key=lambda x:int(x))
|
||||||
|
self.cameras = read_cameras(path)
|
||||||
|
self.subs = subs
|
||||||
|
self.image_args = image_args
|
||||||
|
self.cameras_vis = {sub:cam.copy() for sub, cam in self.cameras.items()}
|
||||||
|
# rescale the camera
|
||||||
|
for cam in self.cameras_vis.values():
|
||||||
|
K = cam['K'].copy()
|
||||||
|
cam['K'][:2, :] *= image_args.scale
|
||||||
|
self.distortMap = {}
|
||||||
|
|
||||||
|
def __call__(self, basename):
|
||||||
|
if self.images == 'none':
|
||||||
|
# 返回空的图像
|
||||||
|
imgs = {sub: self.blank.copy() for sub in self.subs}
|
||||||
|
import ipdb; ipdb.set_trace()
|
||||||
|
else:
|
||||||
|
imgs = {}
|
||||||
|
for sub in self.subs:
|
||||||
|
imgname = join(self.images, sub, basename+self.image_args.ext)
|
||||||
|
if not os.path.exists(imgname):
|
||||||
|
for ext in ['.jpg', '.png']:
|
||||||
|
imgname_ = imgname.replace(self.image_args.ext, ext)
|
||||||
|
if os.path.exists(imgname_):
|
||||||
|
self.image_args.ext = ext
|
||||||
|
imgname = imgname_
|
||||||
|
assert os.path.exists(imgname), imgname
|
||||||
|
img = cv2.imread(imgname)
|
||||||
|
if self.image_args.scale != 1:
|
||||||
|
img = cv2.resize(img, None, fx=self.image_args.scale, fy=self.image_args.scale)
|
||||||
|
if self.image_args.undis:
|
||||||
|
camera = self.cameras_vis[sub]
|
||||||
|
K, D = camera['K'], camera['dist']
|
||||||
|
if sub not in self.distortMap.keys():
|
||||||
|
h, w = img.shape[:2]
|
||||||
|
mapx, mapy = cv2.initUndistortRectifyMap(camera['K'], camera['dist'], None, camera['K'], (w,h), 5)
|
||||||
|
self.distortMap[sub] = (mapx, mapy)
|
||||||
|
mapx, mapy = self.distortMap[sub]
|
||||||
|
img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
|
||||||
|
imgs[sub] = img
|
||||||
|
return imgs, self.cameras_vis
|
||||||
|
|
||||||
|
class Repro:
|
||||||
|
def __init__(self, out, merge='none') -> None:
|
||||||
|
self.out = out
|
||||||
|
os.makedirs(self.out, exist_ok=True)
|
||||||
|
self.merge = merge
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def repro(P, keypoints3d, img):
|
||||||
|
if keypoints3d.shape[1] == 3:
|
||||||
|
keypoints3d = np.hstack((keypoints3d, np.ones((keypoints3d.shape[0], 1))))
|
||||||
|
kcam = np.hstack([keypoints3d[:, :3], np.ones((keypoints3d.shape[0], 1))]) @ P.T
|
||||||
|
kcam = kcam[:, :]/kcam[:, 2:]
|
||||||
|
k2d = np.hstack((kcam, (keypoints3d[:, 3:]>0.)&(kcam[:, 2:] >0.1)))
|
||||||
|
from ..estimator.wrapper_base import bbox_from_keypoints
|
||||||
|
bbox = bbox_from_keypoints(k2d)
|
||||||
|
return k2d, bbox
|
||||||
|
|
||||||
|
def __call__(self, images, results, cameras, basename):
|
||||||
|
imgsout = {}
|
||||||
|
cams = list(images.keys())
|
||||||
|
for nv, cam in enumerate(cams):
|
||||||
|
img = images[cam]
|
||||||
|
outname = join(self.out, basename+'_' + cam +'.jpg')
|
||||||
|
# K可能缩放过了,所以需要重新计算
|
||||||
|
P = cameras[cam]['K'] @ cameras[cam]['RT']
|
||||||
|
for pid, info in results.items():
|
||||||
|
keypoints3d = info['keypoints3d']
|
||||||
|
k2d, bbox = self.repro(P, keypoints3d, img)
|
||||||
|
lw = int(max(bbox[2] - bbox[0], bbox[3] - bbox[1])/50)
|
||||||
|
# plot_bbox(img, bbox, pid=pid, vis_id=pid)
|
||||||
|
plot_keypoints_auto(img, k2d, pid=pid, use_limb_color=False)
|
||||||
|
imgsout[outname] = img
|
||||||
|
if self.merge == 'none':
|
||||||
|
for outname, img in imgsout.items():
|
||||||
|
cv2.imwrite(outname, img)
|
||||||
|
else:
|
||||||
|
outname = join(self.out, basename+'.jpg')
|
||||||
|
out = merge(list(imgsout.values()), square=True)
|
||||||
|
cv2.imwrite(outname, out)
|
||||||
|
|
||||||
|
class Outputs:
|
||||||
|
def __init__(self, out, mode, backend, scene={}) -> None:
|
||||||
|
self.out = out
|
||||||
|
os.makedirs(self.out, exist_ok=True)
|
||||||
|
from .render_func import get_render_func, get_ext
|
||||||
|
self.render_func = get_render_func(mode, backend)
|
||||||
|
self.mode = mode
|
||||||
|
self.ext = get_ext(mode)
|
||||||
|
self.extra_mesh = {}
|
||||||
|
self.scene = []
|
||||||
|
for key, val in scene.items():
|
||||||
|
mesh = load_object(val.module, val.args)
|
||||||
|
log('[vis] Load extra mesh {}'.format(key))
|
||||||
|
self.scene.append(mesh)
|
||||||
|
|
||||||
|
def __call__(self, images, results, cameras, basename):
|
||||||
|
for i, mesh in enumerate(self.scene):
|
||||||
|
results[10000+i] = mesh
|
||||||
|
render_results = self.render_func(images, results, cameras, self.extra_mesh)
|
||||||
|
output = merge(list(render_results.values()), square=True)
|
||||||
|
if output.shape[0] > 10000:
|
||||||
|
scale = 5000./output.shape[0]
|
||||||
|
output = cv2.resize(output, None, fx=scale, fy=scale)
|
||||||
|
outname = join(self.out, basename+self.ext)
|
||||||
|
imwrite(outname, output)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class MIOutputs(Outputs):
|
||||||
|
def __init__(self, out, mode, backend, merge=True, scene={}) -> None:
|
||||||
|
super().__init__(out, mode, backend, scene=scene)
|
||||||
|
self.merge = merge
|
||||||
|
|
||||||
|
def __call__(self, images, results, cameras, basename):
|
||||||
|
# 传个subs进来
|
||||||
|
# save the results to individual folders
|
||||||
|
subs = list(images.keys())
|
||||||
|
outputs = {}
|
||||||
|
for nv, sub in enumerate(subs):
|
||||||
|
if sub in results.keys():
|
||||||
|
result = results[sub]
|
||||||
|
# consider the case that the result is not in the results
|
||||||
|
# especially in multiview results and render novel view
|
||||||
|
else:
|
||||||
|
result = results
|
||||||
|
value0 = list(result.values())[0]
|
||||||
|
if 'vertices' not in value0.keys():
|
||||||
|
continue
|
||||||
|
for i, mesh in enumerate(self.scene):
|
||||||
|
result[10000+i] = mesh
|
||||||
|
if self.mode == 'instance-mask' or self.mode == 'instance-depth':
|
||||||
|
# TODO: use depth to render instance mask and consider occlusion
|
||||||
|
for pid, value in result.items():
|
||||||
|
if 'vertices' not in value.keys():
|
||||||
|
print('[ERROR] vis view {}, pid {}'.format(sub, pid))
|
||||||
|
output = self.render_func({sub:images[sub]},
|
||||||
|
{pid:value},
|
||||||
|
{sub:cameras[sub]}, self.extra_mesh)
|
||||||
|
outname = join(self.out, sub, basename + '_{}'.format(pid) + self.ext)
|
||||||
|
imwrite(outname, output[sub])
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
output = self.render_func({sub:images[sub]},
|
||||||
|
result,
|
||||||
|
{sub:cameras[sub]}, self.extra_mesh)
|
||||||
|
outputs[sub] = output[sub]
|
||||||
|
if len(outputs.keys()) == 0:
|
||||||
|
return 0
|
||||||
|
if self.merge:
|
||||||
|
outname = join(self.out, basename + self.ext)
|
||||||
|
outputs = merge(list(outputs.values()), square=True)
|
||||||
|
imwrite(outname, outputs)
|
||||||
|
else:
|
||||||
|
for nv, sub in enumerate(subs):
|
||||||
|
if sub not in outputs.keys():continue
|
||||||
|
outname = join(self.out, sub, basename + self.ext)
|
||||||
|
imwrite(outname, outputs[sub])
|
||||||
|
return 0
|
Loading…
Reference in New Issue
Block a user