def computeSphericalHarmonics(vn, vc, light_color, components, ignoreFirstMesh=True): # vnflat = [item for sublist in vn for item in sublist] # vcflat = [item for sublist in vc for item in sublist] A_list = [] rangeMeshes = range(len(vn)) for mesh in rangeMeshes: if ignoreFirstMesh and len(vn) > 1: if mesh > 0: A_list += [ SphericalHarmonics(vn=vn[mesh], components=components, light_color=light_color) ] else: A_list += [1.] else: A_list += [ SphericalHarmonics(vn=vn[mesh], components=components, light_color=light_color) ] vc_list = [A_list[mesh] * vc[mesh] for mesh in rangeMeshes] return vc_list
def render_color_model_with_lighting(w, h, v, vn, vc, f, u, sh_comps=None, light_c=ch.ones(3), vlight_pos=None, vlight_color=None, bg_img=None): """renders colored model with lighting effect""" assert(sh_comps is not None or vlight_pos is not None) V = ch.array(v) A = np.zeros_like(v) # SH lighting if sh_comps is not None: A += vc * SphericalHarmonics(vn=vn, components=sh_comps, light_color=light_c) # single point lighting (grey light) if vlight_color is not None and vlight_pos is not None \ and len(vlight_pos.shape) == 1: A += LambertianPointLight(f=f, v=v, num_verts=len(v), light_pos=vlight_pos, light_color=vlight_color, vc=vc) # multiple point lighting (grey light) if vlight_color is not None and vlight_pos is not None \ and len(vlight_pos.shape) == 2: for vlp in vlight_pos: A += LambertianPointLight(f=f, v=v, num_verts=len(v), light_pos=vlp, light_color=vlight_color, vc=vc) black_img = np.array(np.zeros((w, h, 3)), dtype=np.float32) bg_img_ = bg_img if bg_img is not None else black_img rn = ColoredRenderer(camera=u, v=V, f=f, vc=A, background_image=bg_img_, frustum={'width': w, 'height': h, 'near': 0.1, 'far': 20}) return rn.r
def computeSphericalHarmonics(vn, vc, light_color, components): rangeMeshes = range(len(vn)) A_list = [ SphericalHarmonics(vn=vn[mesh], components=components, light_color=light_color) for mesh in rangeMeshes ] vc_list = [A_list[mesh] * vc[mesh] for mesh in rangeMeshes] return vc_list
def computeSphericalHarmonics(vn, vc, light_color, components): # vnflat = [item for sublist in vn for item in sublist] # vcflat = [item for sublist in vc for item in sublist] rangeMeshes = range(len(vn)) A_list = [ SphericalHarmonics(vn=vn[mesh], components=components, light_color=light_color) for mesh in rangeMeshes ] vc_list = [A_list[mesh] * vc[mesh] for mesh in rangeMeshes] return vc_list
def test_earth(): m = get_earthmesh(trans=ch.array([0, 0, 0]), rotation=ch.zeros(3)) # Create V, A, U, f: geometry, brightness, camera, renderer V = ch.array(m.v) A = SphericalHarmonics(vn=VertNormals(v=V, f=m.f), components=[3., 2., 0., 0., 0., 0., 0., 0., 0.], light_color=ch.ones(3)) # camera U = ProjectPoints(v=V, f=[w, w], c=[w / 2., h / 2.], k=ch.zeros(5), t=ch.zeros(3), rt=ch.zeros(3)) f = TexturedRenderer(vc=A, camera=U, f=m.f, bgcolor=[0., 0., 0.], texture_image=m.texture_image, vt=m.vt, ft=m.ft, frustum={ 'width': w, 'height': h, 'near': 1, 'far': 20 }) # Parameterize the vertices translation, rotation = ch.array([0, 0, 8]), ch.zeros(3) f.v = translation + V.dot(Rodrigues(rotation)) observed = f.r np.random.seed(1) # this is reactive # in the sense that changes to values will affect function which depend on them. translation[:] = translation.r + np.random.rand(3) rotation[:] = rotation.r + np.random.rand(3) * .2 # Create the energy E_raw = f - observed E_pyr = gaussian_pyramid(E_raw, n_levels=6, normalization='size') Image.fromarray((observed * 255).astype(np.uint8)).save( os.path.join(save_dir, "reference.png")) step = 0 Image.fromarray((f.r * 255).astype(np.uint8)).save( os.path.join(save_dir, "step_{:05d}.png".format(step))) print('OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS') free_variables = [translation, rotation] ch.minimize({'pyr': E_pyr}, x0=free_variables, callback=create_callback(f)) ch.minimize({'raw': E_raw}, x0=free_variables, callback=create_callback(f))
def test_spherical_harmonics(self): global visualize if visualize: plt.ion() # Get mesh v, f = get_sphere_mesh() ipdb.set_trace() from geometry import VertNormals vn = VertNormals(v=v, f=f) #vn = Ch(mesh.estimate_vertex_normals()) # Get camera cam, frustum = getcam() ipdb.set_trace() # Get renderer from renderer import ColoredRenderer cam.v = v cr = ColoredRenderer() cr.camera = cam cr.camera.openglMat = np.array(mathutils.Matrix.Rotation( np.pi, 4, 'X')) cr.frustum = frustum cr.set(v=v, f=f) # cr = ColoredRenderer(f=f, camera=cam, frustum=frustum, v=v) sh_red = SphericalHarmonics(vn=vn, light_color=np.array([1, 0, 0])) sh_green = SphericalHarmonics(vn=vn, light_color=np.array([0, 1, 0])) cr.vc = sh_red + sh_green ims_baseline = [] for comp_idx, subplot_idx in enumerate( [3, 7, 8, 9, 11, 12, 13, 14, 15]): sh_comps = np.zeros(9) sh_comps[comp_idx] = 1 sh_red.components = Ch(sh_comps) sh_green.components = Ch(-sh_comps) newim = cr.r.reshape((frustum['height'], frustum['width'], 3)) ims_baseline.append(newim) if visualize: plt.subplot(3, 5, subplot_idx) plt.imshow(newim) plt.axis('off') offset = row(.4 * (np.random.rand(3) - .5)) #offset = row(np.array([1.,1.,1.]))*.05 vn_shifted = (vn.r + offset) vn_shifted = vn_shifted / col(np.sqrt(np.sum(vn_shifted**2, axis=1))) vn_shifted = vn_shifted.ravel() vn_shifted[vn_shifted > 1.] = 1 vn_shifted[vn_shifted < -1.] = -1 vn_shifted = Ch(vn_shifted) cr.replace(sh_red.vn, vn_shifted) if True: for comp_idx in range(9): if visualize: plt.figure(comp_idx + 2) sh_comps = np.zeros(9) sh_comps[comp_idx] = 1 sh_red.components = Ch(sh_comps) sh_green.components = Ch(-sh_comps) pred = cr.dr_wrt(vn_shifted).dot( col(vn_shifted.r.reshape(vn.r.shape) - vn.r)).reshape( (frustum['height'], frustum['width'], 3)) if visualize: plt.subplot(1, 2, 1) plt.imshow(pred) plt.title('pred (comp %d)' % (comp_idx, )) plt.subplot(1, 2, 2) newim = cr.r.reshape((frustum['height'], frustum['width'], 3)) emp = newim - ims_baseline[comp_idx] if visualize: plt.imshow(emp) plt.title('empirical (comp %d)' % (comp_idx, )) pred_flat = pred.ravel() emp_flat = emp.ravel() nnz = np.unique( np.concatenate( (np.nonzero(pred_flat)[0], np.nonzero(emp_flat)[0]))) if comp_idx != 0: med_diff = np.median(np.abs(pred_flat[nnz] - emp_flat[nnz])) med_obs = np.median(np.abs(emp_flat[nnz])) if comp_idx == 4 or comp_idx == 8: self.assertTrue(med_diff / med_obs < .6) else: self.assertTrue(med_diff / med_obs < .3) if visualize: plt.axis('off')