From 3e21908e82dc119b112bab80a6568fe58cb1d52e Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Fri, 11 Jul 2014 19:54:29 -0400 Subject: [PATCH 01/56] Bring in BL current and history MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bring in history from BL… --- Makefile | 8 +--- camera.py | 20 +++++++++- common.py | 34 ++++++++++++++++- filters.py | 7 +++- renderer.py | 60 ++++++++++++++++++++++-------- setup.py | 95 +++++++++++++++++++++++++++++++---------------- test_dr/common.py | 4 +- utils.py | 10 +++-- 8 files changed, 173 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 131a2ed..ded68e6 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,7 @@ -all: contexts/ctx_mac.c contexts/ctx_mesa.c +all: python2.7 setup.py build_ext --inplace -contexts/ctx_mac.c: - make -C contexts - -contexts/ctx_mesa.c: - make -C contexts - sdist: all python setup.py sdist && rsync -avz dist/opendr-0.5.tar.gz files:~/opendr/latest.tgz diff --git a/camera.py b/camera.py index 164b2e9..19153cf 100755 --- a/camera.py +++ b/camera.py @@ -112,7 +112,20 @@ def unproject_points(self, uvd, camera_space=False): ch.minimize(cam - uvd, x0=[cam.v], method='dogleg', options={'disp': 0}) result = cam.v.r else: - xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2)).copy()), np.asarray(cam.camera_mtx), cam.k.r) + try: + xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2)).copy()), np.asarray(cam.camera_mtx), cam.k.r) + except AttributeError: + import cv + num_row, num_col = uvd[:,:2].reshape((1,-1,2)).shape[0:2] + xy_undistorted_camspace_mat = cv.CreateMat(num_row, num_col, cv.CV_64FC2) + dist = cv.CreateMat(1, 5, cv.CV_32FC1) + for idx in range(cam.k.r.size): + dist[0, idx] = cam.k.r[idx] + cv.UndistortPoints(cv.fromarray(np.asarray(uvd[:,:2].reshape((1,-1,2))).copy()), + xy_undistorted_camspace_mat, + cv.fromarray(np.asarray(cam.camera_mtx)), + dist) + xy_undistorted_camspace = np.asarray(xy_undistorted_camspace_mat) xyz_camera_space = np.hstack((xy_undistorted_camspace.squeeze(), col(uvd[:,2]))) xyz_camera_space[:,:2] *= col(xyz_camera_space[:,2]) # scale x,y by z if camera_space: @@ -129,6 +142,11 @@ def unproject_depth_image(self, depth_image, camera_space=False): xyz = self.unproject_points(uvd, camera_space=camera_space) return xyz.reshape((depth_image.shape[0], depth_image.shape[1], -1)) + def project_depth_point(self, xyz): + cam = ProjectPoints3D(**{k: getattr(self, k) for k in self.dterms if hasattr(self, k)}) + uvd = cam.camera_mtx.dot(xyz) + uv = uvd[:2] / uvd[-1] + return uv @depends_on('f','c') def camera_mtx(self): diff --git a/common.py b/common.py index c4bb27b..1f9d4eb 100755 --- a/common.py +++ b/common.py @@ -305,12 +305,20 @@ def dr_wrt_vc(visible, visibility, f, barycentric, frustum, v_size): return result -def draw_visibility_image(gl, v, f, boundarybool_image=None): +def draw_visibility_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, y0=None, y1=None): v = np.asarray(v) gl.Disable(GL_TEXTURE_2D) gl.DisableClientState(GL_TEXTURE_COORD_ARRAY) result = draw_visibility_image_internal(gl, v, f) + + # Crop + if x0 != None and isinstance(x0, int): + result[:y0] = -1 + result[y1:] = -1 + result[y0:y1, :x0] = -1 + result[y0:y1, x1:] = -1 + if boundarybool_image is None: return result @@ -321,6 +329,13 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None): return result gl.PolygonMode(GL_FRONT_AND_BACK, GL_LINE) result2 = draw_visibility_image_internal(gl, v, f[faces_to_draw]) + + if x0 != None and isinstance(x0, int): + result2[:y0] = -1 + result2[y1:] = -1 + result2[y0:y1, :x0] = -1 + result2[y0:y1, x1:] = -1 + gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) bbi = boundarybool_image @@ -426,14 +441,29 @@ def draw_texcoord_image(glf, v, f, vt, ft, boundarybool_image=None): return result -def draw_barycentric_image(gl, v, f, boundarybool_image=None): +def draw_barycentric_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, + y0=None, y1=None): v = np.asarray(v) without_overdraw = draw_barycentric_image_internal(gl, v, f) + # Crop + if x0 != None and isinstance(x0, int): + without_overdraw[:y0] = -1 + without_overdraw[y1:] = -1 + without_overdraw[y0:y1, :x0] = -1 + without_overdraw[y0:y1, x1:] = -1 + if boundarybool_image is None: return without_overdraw gl.PolygonMode(GL_FRONT_AND_BACK, GL_LINE) overdraw = draw_barycentric_image_internal(gl, v, f) + # Crop + if x0 != None and isinstance(x0, int): + overdraw[:y0] = -1 + overdraw[y1:] = -1 + overdraw[y0:y1, :x0] = -1 + overdraw[y0:y1, x1:] = -1 + gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) bbi = np.atleast_3d(boundarybool_image) diff --git a/filters.py b/filters.py index 6d35135..9a9bb3d 100755 --- a/filters.py +++ b/filters.py @@ -70,6 +70,7 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape) cur_imshape = cur_obj.output_shape output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label,ik)) + if not as_list: andit = lambda a : reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), a) @@ -139,8 +140,10 @@ def halfsampler_for(shape): def filter_for_nopadding(shape, kernel): assert(len(shape)==3) - new_shape = (shape - np.array([kernel.shape[0] - 1, kernel.shape[1] - 1, 0])).astype(np.uint32) - + #new_shape = (shape - np.array([kernel.shape[0] - 1, kernel.shape[1] - 1, 0])).astype(np.uint32) + new_shape = (shape - np.array([kernel.shape[0] - 1, kernel.shape[1] - 1, 0])) + new_shape[new_shape<0] = 0.0 + new_shape = new_shape.astype(np.uint32) IS = [] JS = [] diff --git a/renderer.py b/renderer.py index 4dff414..46f6912 100755 --- a/renderer.py +++ b/renderer.py @@ -57,7 +57,8 @@ def boundaryid_image(self): @depends_on('f', 'frustum', 'camera', 'overdraw') def visibility_image(self): self._call_on_changed() - return draw_visibility_image(self.glb, self.v.r, self.f, self.boundarybool_image if self.overdraw else None) + return draw_visibility_image(self.glb, self.v.r, self.f, + self.boundarybool_image if self.overdraw else None) @depends_on(terms+dterms) def boundarybool_image(self): @@ -82,11 +83,8 @@ def fpe(self): return self.primitives_per_edge[0] - - - class DepthRenderer(BaseRenderer): - terms = 'f', 'frustum', 'background_image','overdraw' + terms = 'f', 'frustum', 'background_image','overdraw', 'x0', 'x1', 'y0', 'y1' dterms = 'camera', 'v' @@ -197,6 +195,39 @@ def depth_image(self): return result + @depends_on('f', 'frustum', 'camera', 'overdraw', 'x0', 'x1', 'y0', 'y1') + def visibility_image(self): + self._call_on_changed() + if hasattr(self, 'x0') and self.x0 != None: + return draw_visibility_image(self.glb, self.v.r, self.f, + self.boundarybool_image if self.overdraw else None, + self.x0, self.x1, self.y0, self.y1) + else: + return draw_visibility_image(self.glb, self.v.r, self.f, + self.boundarybool_image if self.overdraw else None) + + @depends_on(terms+dterms) + def boundaryid_image(self): + self._call_on_changed() + if hasattr(self, 'x0') and self.x0 != None: + return draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, + self.fpe, self.camera, + self.x0, self.x1, self.y0, self.y1) + else: + return draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, + self.fpe, self.camera) + + @depends_on('f', 'frustum', 'camera', 'overdraw', 'x0', 'x1', 'y0', 'y1') + def barycentric_image(self): + self._call_on_changed() + if hasattr(self, 'x0') and self.x0 != None: + return draw_barycentric_image(self.glf, self.v.r, self.f, + self.boundarybool_image if self.overdraw else None, + self.x0, self.x1, self.y0, self.y1) + else: + return draw_barycentric_image(self.glf, self.v.r, self.f, + self.boundarybool_image if self.overdraw else None) + def getDepthMesh(self, depth_image=None): self._call_on_changed() # make everything is up-to-date v = self.glb.getDepthCloud(depth_image) @@ -266,8 +297,6 @@ class ColoredRenderer(BaseRenderer): terms = 'f', 'frustum', 'background_image', 'overdraw' dterms = 'vc', 'camera', 'bgcolor' - - def compute_r(self): tmp = self.camera.r return self.color_image.reshape((self.frustum['height'], self.frustum['width'], -1)) @@ -326,8 +355,6 @@ def on_changed(self, which): def flow_to(self, v_next, cam_next=None): return common.flow_to(self, v_next, cam_next) - - def filter_for_triangles(self, which_triangles): cim = self.color_image vim = self.visibility_image+1 @@ -367,7 +394,6 @@ def draw_color_image(self, gl): return result - @depends_on(dterms+terms) def color_image(self): gl = self.glf @@ -383,10 +409,6 @@ def color_image(self): boundarybool_image = np.atleast_3d(self.boundarybool_image) return overdraw*boundarybool_image + no_overdraw*(1-boundarybool_image) - - - - @depends_on('f', 'frustum', 'camera') def boundary_images(self): self._call_on_changed() @@ -651,7 +673,7 @@ def compute_vpe_boundary_idxs(v, f, camera, fpe): -def draw_boundaryid_image(gl, v, f, vpe, fpe, camera): +def draw_boundaryid_image(gl, v, f, vpe, fpe, camera, x0=None, x1=None, y0=None, y1=None): if False: @@ -669,6 +691,14 @@ def draw_boundaryid_image(gl, v, f, vpe, fpe, camera): if len(lines_e)==0: return np.ones((gl.height, gl.width)).astype(np.int32) * 4294967295 visibility = draw_edge_visibility(gl, lines_v, lines_e, f, hidden_wireframe=True) + + # Crop + if x0 != None and isinstance(x0, int): + visibility[:y0] = -1 + visibility[y1:] = -1 + visibility[y0:y1, :x0] = -1 + visibility[y0:y1, x1:] = -1 + shape = visibility.shape visibility = visibility.ravel() visible = np.nonzero(visibility.ravel() != 4294967295)[0] diff --git a/setup.py b/setup.py index 6246264..77fbb41 100644 --- a/setup.py +++ b/setup.py @@ -4,19 +4,54 @@ See LICENCE.txt for licensing and contact information. """ -from distutils.core import setup +from setuptools import setup from distutils.extension import Extension from Cython.Build import cythonize - -from os.path import exists, join import numpy import platform -import re - -import contexts.autogen - - -def setup_opendr(args): +import os + +# setuptools DWIM monkey-patch madness +# http://mail.python.org/pipermail/distutils-sig/2007-September/thread.html#8204 +import sys +if 'setuptools.extension' in sys.modules: + m = sys.modules['setuptools.extension'] + m.Extension.__dict__ = m._Extension.__dict__ + +context_dir = os.path.join(os.path.dirname(__file__), 'contexts') + +def download_osmesa(): + import os, re, zipfile + from utils import wget + mesa_dir = os.path.join(context_dir,'OSMesa') + if not os.path.exists(mesa_dir): + sysinfo = platform.uname() + osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2]) + zip_fname = os.path.join(context_dir, osmesa_fname) + if not os.path.exists(zip_fname): + print "Downloading %s" % osmesa_fname + # MPI url was: http://files.is.tue.mpg.de/mloper/opendr/osmesa/%s + wget('https://s3.amazonaws.com/bodylabs-assets/public/osmesa/%s' % (osmesa_fname,), dest_fname=zip_fname) + assert(os.path.exists(zip_fname)) + with zipfile.ZipFile(zip_fname, 'r') as z: + for f in filter(lambda x: re.search('[ah]$', x), z.namelist()): + z.extract(f, path=context_dir) + assert(os.path.exists(mesa_dir)) + + +def autogen_opengl_sources(): + import os + sources = [ os.path.join(context_dir, x) for x in ['_constants.py', '_functions.pyx'] ] + if not all([ os.path.exists(x) for x in sources ]): + print "Autogenerating opengl sources" + from contexts import autogen + autogen.main() + for x in sources: + assert(os.path.exists(x)) + + +def setup_opendr(ext_modules): + ext_modules=cythonize(ext_modules) setup(name='opendr', version='0.5', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], @@ -26,55 +61,49 @@ def setup_opendr(args): url = 'http://files.is.tue.mpg/mloper/opendr/', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - **args + install_requires=['cython'], + ext_modules=ext_modules, ) -def add_mesa_args(args): +def mesa_ext(): libraries = ['OSMesa', 'GL', 'GLU'] + extra_args = [] if platform.system()=='Darwin': libraries.append('talloc') - ctx_mesa_extension = Extension("contexts.ctx_mesa", ['contexts/ctx_mesa.c'], + extra_args.append('-Qunused-arguments') + return Extension("contexts.ctx_mesa", ['contexts/ctx_mesa.pyx'], language="c", library_dirs=['contexts/OSMesa/lib'], depends=['contexts/_constants.py'], define_macros = [('__OSMESA__', 1)], + include_dirs=['.', numpy.get_include(), 'contexts/OSMesa/include'], libraries=libraries, - extra_compile_args=['-Qunused-arguments'], - extra_link_args=['-Qunused-arguments']) - - args['ext_modules'].append(ctx_mesa_extension) - args['include_dirs'] += ['.', numpy.get_include(), 'contexts/OSMesa/include'] + extra_compile_args=extra_args, + extra_link_args=extra_args) -def add_mac_args(args): - ctx_mac_extension = Extension("contexts.ctx_mac", ['contexts/ctx_mac.c', 'contexts/ctx_mac_internal.c'], +def mac_ext(): + return Extension("contexts.ctx_mac", ['contexts/ctx_mac.pyx', 'contexts/ctx_mac_internal.c'], language="c", depends=['contexts/_constants.py', 'contexts/ctx_mac_internal.h'], + include_dirs=['.', numpy.get_include()], extra_compile_args=['-Qunused-arguments'], extra_link_args=['-Qunused-arguments']) - args['ext_modules'].append(ctx_mac_extension) - args['include_dirs'] += ['.', numpy.get_include()] - - def main(): from contexts.fix_warnings import fix_warnings fix_warnings() # Get osmesa and some processed files ready - contexts.autogen.main() + download_osmesa() + autogen_opengl_sources() - # Get context extensions ready - setup_args = {'ext_modules': [], 'include_dirs': []} - add_mesa_args(setup_args) + # Get context extensions ready & build if platform.system() == 'Darwin': - add_mac_args(setup_args) - - #setup_args['ext_modules'] = cythonize(setup_args['ext_modules']) - - # Build - setup_opendr(setup_args) + setup_opendr([mesa_ext(), mac_ext()]) + else: + setup_opendr([mesa_ext()]) if __name__ == '__main__': diff --git a/test_dr/common.py b/test_dr/common.py index 974e8a4..d5c9273 100644 --- a/test_dr/common.py +++ b/test_dr/common.py @@ -15,14 +15,14 @@ def get_earthmesh(trans, rotation): if not hasattr(get_earthmesh, 'm'): def wg(url): - dest = join(split(__file__)[0], split(url)[1]) + dest = join('/tmp', split(url)[1]) if not exists(dest): wget(url, dest) wg('http://files.is.tue.mpg.de/mloper/opendr/images/nasa_earth.obj') wg('http://files.is.tue.mpg.de/mloper/opendr/images/nasa_earth.mtl') wg('http://files.is.tue.mpg.de/mloper/opendr/images/nasa_earth.jpg') - fname = join(split(__file__)[0], 'nasa_earth.obj') + fname = join('/tmp', 'nasa_earth.obj') mesh = load_mesh(fname) mesh.v = np.asarray(mesh.v, order='C') diff --git a/utils.py b/utils.py index 87451fd..759cd02 100644 --- a/utils.py +++ b/utils.py @@ -15,7 +15,6 @@ def mstack(vs, fs): return v, f - def wget(url, dest_fname=None): import urllib2 from os.path import split, join @@ -25,7 +24,12 @@ def wget(url, dest_fname=None): dest_fname = join(curdir, split(url)[1]) try: - contents = urllib2.urlopen(url).read() + source = urllib2.urlopen(url) + with open(dest_fname, 'w') as f: + while True: + contents = source.read(8000) + if contents == "": + break + f.write(contents) except: raise Exception('Unable to get url: %s' % (url,)) - open(dest_fname, 'w').write(contents) From 9145ca88efac30e9912aec64238be782cc7b6db4 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Fri, 11 Jul 2014 20:02:38 -0400 Subject: [PATCH 02/56] Removed contexts/setup.py --- contexts/setup.py | 92 ----------------------------------------------- 1 file changed, 92 deletions(-) delete mode 100644 contexts/setup.py diff --git a/contexts/setup.py b/contexts/setup.py deleted file mode 100644 index 68a3b38..0000000 --- a/contexts/setup.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -Author(s): Matthew Loper - -See LICENCE.txt for licensing and contact information. -""" - -__all__ = ['build_contexts'] - -from os.path import join, split, exists -from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext -import numpy -import re -import platform -from opendr.utils import wget -import zipfile - - -def lf(fname): - return join(split(__file__)[0], fname) - -def is_osx(): - return bool(re.search('darwin', platform.platform(), re.I)) - -def ctx_mesa_libraries(): - libraries = ['OSMesa', 'GL', 'GLU'] - if is_osx(): - libraries.append('talloc') - else: - libraries.append('stdc++') - return libraries - -def build_contexts(): - if not exists(lf('_constants.py')) or not exists(lf('_functions.pyx')): - import autogen - autogen.main() - assert(exists(lf('_constants.py')) and exists(lf('_functions.pyx'))) - ctx_mesa_extension = Extension("ctx_mesa", [lf('ctx_mesa.pyx')], - language="c", - library_dirs=[lf('OSMesa/lib')], - depends=[lf('_functions.pyx'), lf('_constants.py'), lf('ctx_base.pyx')], - define_macros = [('__OSMESA__', 1)], - libraries=ctx_mesa_libraries(), - extra_compile_args=['-Wno-unused-function', '-Wno-implicit-function-declaration'], - extra_link_args=['-Wno-unused-function', '-Wno-implicit-function-declaration']) - - - setup( - cmdclass = {'build_ext': build_ext}, - ext_modules = [ctx_mesa_extension], - include_dirs = ['.', numpy.get_include(), lf('OSMesa/include')], - ) - - if platform.system()=='Darwin': - ctx_mac_extension = Extension("ctx_mac", [lf('ctx_mac.pyx'), lf('ctx_mac_internal.c')], - language="c", - depends=[lf('_functions.pyx'), lf('_constants.py'), lf('ctx_base.pyx'), lf('ctx_mac_internal.h')], - extra_compile_args=['-Wno-unused-function', '-Wno-implicit-function-declaration'], - extra_link_args=['-Wno-unused-function', '-Wno-implicit-function-declaration']) - - - - setup( - cmdclass = {'build_ext': build_ext}, - ext_modules = [ctx_mac_extension], - include_dirs = ['.', numpy.get_include()] - ) - - -def download_osmesa(): - curdir = '.' - mesadir = join(curdir,'OSMesa') - if not exists(mesadir): - sysinfo = platform.uname() - osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2]) - dest_fname = '%s/%s' % (curdir, osmesa_fname,) - if not exists(dest_fname): - wget('http://files.is.tue.mpg.de/mloper/opendr/osmesa/%s' % (osmesa_fname,), dest_fname=dest_fname) - assert(exists(dest_fname)) - - with zipfile.ZipFile(dest_fname, 'r') as z: - for f in filter(lambda x: re.search('[ah]$', x), z.namelist()): - z.extract(f, path='.') - assert(exists(mesadir)) - - -if __name__ == '__main__': - from fix_warnings import fix_warnings - fix_warnings() - download_osmesa() - build_contexts() From b0f0ae409860b7b38c874715ee35fc9c019ab443 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Mon, 14 Jul 2014 09:14:53 -0400 Subject: [PATCH 03/56] Added num_channels to renderers. Colored renderer can now have that set to any number between 1 and 3 (and is 3 by default). Conflicts: renderer.py --- common.py | 27 ++++--- lighting.py | 44 +++++----- renderer.py | 84 ++++++++++++++----- test_dr/test_renderer.py | 169 ++++++++++++++++++++++----------------- test_dr/test_sh.py | 4 +- 5 files changed, 202 insertions(+), 126 deletions(-) diff --git a/common.py b/common.py index 1f9d4eb..951465d 100755 --- a/common.py +++ b/common.py @@ -271,23 +271,26 @@ def flow_to(self, v_next, cam_next): return flow_im -def dr_wrt_bgcolor(visibility, frustum): +def dr_wrt_bgcolor(visibility, frustum, num_channels): invisible = np.nonzero(visibility.ravel() == 4294967295)[0] IS = invisible JS = np.zeros(len(IS)) data = np.ones(len(IS)) # color image, so 3 channels - IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) - JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) - data = np.concatenate((data, data, data)) + IS = np.concatenate([IS*num_channels+k for k in range(num_channels)]) + JS = np.concatenate([JS*num_channels+k for k in range(num_channels)]) + data = np.concatenate([data for i in range(num_channels)]) + # IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) + # JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) + # data = np.concatenate((data, data, data)) ij = np.vstack((IS.ravel(), JS.ravel())) - result = sp.csc_matrix((data, ij), shape=(frustum['width']*frustum['height']*3, 3)) + result = sp.csc_matrix((data, ij), shape=(frustum['width']*frustum['height']*num_channels, num_channels)) return result -def dr_wrt_vc(visible, visibility, f, barycentric, frustum, v_size): +def dr_wrt_vc(visible, visibility, f, barycentric, frustum, vc_size, num_channels): # Each pixel relies on three verts IS = np.tile(col(visible), (1, 3)).ravel() JS = col(f[visibility.ravel()[visible]].ravel()) @@ -295,13 +298,15 @@ def dr_wrt_vc(visible, visibility, f, barycentric, frustum, v_size): bc = barycentric.reshape((-1,3)) data = np.asarray(bc[visible,:], order='C').ravel() - # color image, so 3 channels - IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) - JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) - data = np.concatenate((data, data, data)) + IS = np.concatenate([IS*num_channels+k for k in range(num_channels)]) + JS = np.concatenate([JS*num_channels+k for k in range(num_channels)]) + data = np.concatenate([data for i in range(num_channels)]) + # IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) + # JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) + # data = np.concatenate((data, data, data)) ij = np.vstack((IS.ravel(), JS.ravel())) - result = sp.csc_matrix((data, ij), shape=(frustum['width']*frustum['height']*3, v_size)) + result = sp.csc_matrix((data, ij), shape=(frustum['width']*frustum['height']*num_channels, vc_size)) return result diff --git a/lighting.py b/lighting.py index eae6141..11ebcba 100755 --- a/lighting.py +++ b/lighting.py @@ -57,6 +57,10 @@ class SphericalHarmonics(Ch): np.sqrt(15)/d_sqrt_pi, np.sqrt(15)/(2*d_sqrt_pi)]) + @property + def num_channels(self): + return self.light_color.size + def on_changed(self, which): if 'vn' in which: vn = self.vn.r.reshape((-1,3)) @@ -70,10 +74,11 @@ def on_changed(self, which): self.num_verts = self.sh_coeffs.shape[0] if 'light_color' in which or self.mtx.shape[1] != self.num_verts: - IS = np.arange(self.num_verts*3) - JS = np.repeat(np.arange(self.num_verts), 3) - data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() - self.mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) + nc = self.num_channels + IS = np.arange(self.num_verts*nc) + JS = np.repeat(np.arange(self.num_verts), nc) + data = (row(self.light_color)*np.ones((self.num_verts, nc))).ravel() + self.mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*nc, self.num_verts)) def compute_r(self): @@ -81,7 +86,7 @@ def compute_r(self): n = len(comps) result = self.mtx.dot(self.sh_coeffs[:,:n].dot(col(self.components.r))) result[result<0] = 0 - return result.reshape((-1,3)) + return result.reshape((-1,self.num_channels)) def compute_dr_wrt(self, wrt): comps = np.zeros(9) @@ -159,16 +164,19 @@ def on_changed(self, which): self._lpl.a.a.a = self.ldn.reshape((-1,1)) if 'num_verts' in which or 'light_color' in which: - IS = np.arange(self.num_verts*3) - JS = np.repeat(np.arange(self.num_verts), 3) - data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() - mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) - self._lpl.a.a.b = self.light_color.reshape((1,3)) + # nc = self.num_channels + # IS = np.arange(self.num_verts*nc) + # JS = np.repeat(np.arange(self.num_verts), 3) + # data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() + # mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) + self._lpl.a.a.b = self.light_color.reshape((1,self.num_channels)) if 'vc' in which: - self._lpl.a.b = self.vc.reshape((-1,3)) + self._lpl.a.b = self.vc.reshape((-1,self.num_channels)) - + @property + def num_channels(self): + return self.light_color.size def compute_r(self): return self._lpl.r @@ -179,12 +187,12 @@ def compute_dr_wrt(self, wrt): -def compute_light_repeat(num_verts): - IS = np.arange(num_verts*3) - JS = IS % 3 - data = np.ones_like(IS, dtype=np.float64) - ij = np.vstack((row(IS), row(JS))) - return sp.csc_matrix((data, ij), shape=(num_verts*3, 3)) +# def compute_light_repeat(num_verts): +# IS = np.arange(num_verts*3) +# JS = IS % 3 +# data = np.ones_like(IS, dtype=np.float64) +# ij = np.vstack((row(IS), row(JS))) +# return sp.csc_matrix((data, ij), shape=(num_verts*3, 3)) def LightDotNormal(num_verts): diff --git a/renderer.py b/renderer.py index 46f6912..e0bbc93 100755 --- a/renderer.py +++ b/renderer.py @@ -66,6 +66,10 @@ def boundarybool_image(self): boundaryid_image = self.boundaryid_image return np.asarray(boundaryid_image != 4294967295, np.uint32).reshape(boundaryid_image.shape) + @property + def shape(self): + raise NotImplementedError('Should be implemented in inherited class.') + @property def v(self): return self.camera.v @@ -88,6 +92,10 @@ class DepthRenderer(BaseRenderer): dterms = 'camera', 'v' + @property + def shape(self): + return (self.frustum['height'], self.frustum['width']) + def compute_r(self): tmp = self.camera.r return self.depth_image.reshape((self.frustum['height'], self.frustum['width'])) @@ -250,6 +258,10 @@ class BoundaryRenderer(BaseRenderer): terms = 'f', 'frustum', 'num_channels' dterms = 'camera', + @property + def shape(self): + return (self.frustum['height'], self.frustum['width'], self.num_channels) + def compute_r(self): tmp = self.camera.r return self.color_image @@ -267,7 +279,6 @@ def compute_dr_wrt(self, wrt): barycentric = self.barycentric_image return common.dImage_wrt_2dVerts(self.color_image, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.vpe) - def on_changed(self, which): if 'frustum' in which: @@ -294,12 +305,21 @@ def color_image(self): class ColoredRenderer(BaseRenderer): - terms = 'f', 'frustum', 'background_image', 'overdraw' + terms = 'f', 'frustum', 'background_image', 'overdraw', 'num_channels' dterms = 'vc', 'camera', 'bgcolor' - + + @property + def shape(self): + if not hasattr(self, 'num_channels'): + self.num_channels = 3 + if self.num_channels > 1: + return (self.frustum['height'], self.frustum['width'], self.num_channels) + else: + return (self.frustum['height'], self.frustum['width']) + def compute_r(self): tmp = self.camera.r - return self.color_image.reshape((self.frustum['height'], self.frustum['width'], -1)) + return self.color_image # .reshape((self.frustum['height'], self.frustum['width'], -1)).squeeze() def compute_dr_wrt(self, wrt): if wrt is not self.camera and wrt is not self.vc and wrt is not self.bgcolor: @@ -322,10 +342,10 @@ def compute_dr_wrt(self, wrt): return common.dImage_wrt_2dVerts(color, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) elif wrt is self.vc: - return common.dr_wrt_vc(visible, visibility, self.f, barycentric, self.frustum, self.v.size) + return common.dr_wrt_vc(visible, visibility, self.f, barycentric, self.frustum, self.vc.size, num_channels=self.num_channels) elif wrt is self.bgcolor: - return common.dr_wrt_bgcolor(visibility, self.frustum) + return common.dr_wrt_bgcolor(visibility, self.frustum, num_channels=self.num_channels) def on_changed(self, which): @@ -341,16 +361,19 @@ def on_changed(self, which): setup_camera(self.glb, self.camera, self.frustum) setup_camera(self.glf, self.camera, self.frustum) + if not hasattr(self, 'num_channels'): + self.num_channels = 3 + if not hasattr(self, 'bgcolor'): - self.bgcolor = Ch(np.array([.5,.5,.5])) + self.bgcolor = Ch(np.array([.5]*self.num_channels)) which.add('bgcolor') if not hasattr(self, 'overdraw'): self.overdraw = True if 'bgcolor' in which or ('frustum' in which and hasattr(self, 'bgcolor')): - self.glf.ClearColor(self.bgcolor.r[0], self.bgcolor.r[1], self.bgcolor.r[2], 1.) - + self.glf.ClearColor(self.bgcolor.r[0], self.bgcolor.r[1%self.num_channels], self.bgcolor.r[2%self.num_channels], 1.) + def flow_to(self, v_next, cam_next=None): return common.flow_to(self, v_next, cam_next) @@ -380,19 +403,23 @@ def boundarycolor_image(self): def draw_color_image(self, gl): self._call_on_changed() - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + try: + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - # use face colors if given - draw_colored_verts(gl, self.v.r, self.f, self.vc.r) + # use face colors if given + # FIXME: this won't work for 2 channels + draw_colored_verts(gl, self.v.r, self.f, self.vc.r) - result = np.asarray(deepcopy(gl.getImage()), np.float64) + result = np.asarray(deepcopy(gl.getImage()[:,:,:self.num_channels].squeeze()), np.float64) - if hasattr(self, 'background_image'): - bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,3)) - fg_px = 1 - bg_px - result = bg_px * self.background_image + fg_px * result + if hasattr(self, 'background_image'): + bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,self.num_channels)).squeeze() + fg_px = 1 - bg_px + result = bg_px * self.background_image + fg_px * result - return result + return result + except: + import pdb; pdb.set_trace() @depends_on(dterms+terms) def color_image(self): @@ -406,8 +433,11 @@ def color_image(self): gl.PolygonMode(GL_FRONT_AND_BACK, GL_LINE) overdraw = self.draw_color_image(gl) gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) - boundarybool_image = np.atleast_3d(self.boundarybool_image) - return overdraw*boundarybool_image + no_overdraw*(1-boundarybool_image) + + boundarybool_image = self.boundarybool_image + if self.num_channels > 1: + boundarybool_image = np.atleast_3d(boundarybool_image) + return np.asarray((overdraw*boundarybool_image + no_overdraw*(1-boundarybool_image)), order='C') @depends_on('f', 'frustum', 'camera') def boundary_images(self): @@ -434,6 +464,14 @@ class TexturedRenderer(ColoredRenderer): def __del__(self): self.release_textures() + + @property + def shape(self): + return (self.frustum['height'], self.frustum['width'], 3) + + @property + def num_channels(self): + return 3 def release_textures(self): if hasattr(self, 'textureID'): @@ -859,12 +897,16 @@ def _setup_camera(gl, cx, cy, fx, fy, w, h, near, far, view_matrix, k): def draw_colored_verts(gl, v, f, vc): + # TODO: copying is inefficient here + if vc.shape[1] != 3: + vc = np.vstack((vc[:,0], vc[:,1%vc.shape[1]], vc[:,2%vc.shape[1]])).T.copy() + assert(vc.shape[1]==3) gl.EnableClientState(GL_VERTEX_ARRAY); gl.EnableClientState(GL_COLOR_ARRAY); gl.VertexPointer(np.ascontiguousarray(v).reshape((-1,3))); gl.ColorPointerd(np.ascontiguousarray(vc).reshape((-1,3))); gl.DrawElements(GL_TRIANGLES, np.asarray(f, np.uint32).ravel()) - + def draw_noncolored_verts(gl, v, f): gl.EnableClientState(GL_VERTEX_ARRAY); gl.DisableClientState(GL_COLOR_ARRAY); diff --git a/test_dr/test_renderer.py b/test_dr/test_renderer.py index b62832a..f90528d 100755 --- a/test_dr/test_renderer.py +++ b/test_dr/test_renderer.py @@ -22,6 +22,7 @@ from chumpy.utils import row, col from opendr.lighting import * from opendr.test_dr.common import get_earthmesh, process +from collections import OrderedDict @@ -58,26 +59,36 @@ def load_basics(self): camera, frustum = getcam() mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) - lighting = LambertianPointLight( - f=mesh.f, - num_verts=len(mesh.v), - light_pos=np.array([-1000,-1000,-1000]), - vc=mesh.vc, + lighting_3channel = LambertianPointLight( + f=mesh.f, + num_verts=len(mesh.v), + light_pos=np.array([-1000,-1000,-1000]), + vc=mesh.vc, light_color=np.array([1., 1., 1.])) - + lighting_1channel = LambertianPointLight( + f=mesh.f, + num_verts=len(mesh.v), + light_pos=np.array([-1000,-1000,-1000]), + vc=mesh.vc.mean(axis=1).reshape((-1,1)), + light_color=np.array([1.])) + bgcolor = np.array([0.,0.,0.]) renderers = [ - ColoredRenderer(f=mesh.f, camera=camera, frustum=frustum, bgcolor=bgcolor), - TexturedRenderer(f=mesh.f, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor)] - - return mesh, lighting, camera, frustum, renderers + ColoredRenderer(f=mesh.f, camera=camera, frustum=frustum, bgcolor=bgcolor, num_channels=3), + TexturedRenderer(f=mesh.f, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor), + ColoredRenderer(f=mesh.f, camera=camera, frustum=frustum, bgcolor=bgcolor[0], num_channels=1)] + + lightings = {1: lighting_1channel, 3: lighting_3channel} + return mesh, lightings, camera, frustum, renderers def test_distortion(self): - mesh, lighting, camera, frustum, renderers = self.load_basics() - lighting.light_pos = -lighting.light_pos * 100. + mesh, lightings, camera, frustum, renderers = self.load_basics() renderer = renderers[1] + lighting = lightings[renderer.num_channels] + lighting.light_pos = -lighting.light_pos * 100. + mesh = get_earthmesh(trans=np.array([0,0,-8]), rotation = np.array([math.pi/2.,0,0])) mesh_verts = Ch(mesh.v.flatten()) renderer.camera = camera @@ -123,20 +134,21 @@ def test_distortion(self): import matplotlib.pyplot as plt plt.ion() - plt.figure() - plt.subplot(2,2,1) + matplotlib.rcParams.update({'font.size': 18}) + plt.figure(figsize=(6*3, 2*3)) + plt.subplot(1,4,1) plt.imshow(im_original) plt.title('original') - plt.subplot(2,2,2) + plt.subplot(1,4,2) plt.imshow(im_distorted) plt.title('distorted') - plt.subplot(2,2,3) + plt.subplot(1,4,3) plt.imshow(im_undistorted) plt.title('undistorted by opencv') - plt.subplot(2,2,4) + plt.subplot(1,4,4) plt.imshow(im_undistorted - im_original + .5) plt.title('diff') @@ -149,19 +161,20 @@ def test_distortion(self): def test_cam_derivatives(self): - mesh, lighting, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, frustum, renderers = self.load_basics() camparms = { - 'c': {'mednz' : 1.5e-2, 'meannz': 2.5e-2, 'desc': 'center of proj diff', 'eps0': 2., 'eps1': .1}, - 'f': {'mednz' : 2.5e-2, 'meannz': 6e-2, 'desc': 'focal diff', 'eps0': 10., 'eps1': .1}, - 't': {'mednz' : 3e-2, 'meannz': 8e-2, 'desc': 'trans diff', 'eps0': .5, 'eps1': .1}, - 'rt': {'mednz' : 8e-2, 'meannz': 1.8e-1, 'desc': 'rot diff', 'eps0': 0.2, 'eps1': .5}, - 'k': {'mednz' : 5e-2, 'meannz': 1.5e-1, 'desc': 'distortion diff', 'eps0': .5, 'eps1': .05} + 'c': {'mednz' : 1.9e-2, 'meannz': 4.0e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, + #'f': {'mednz' : 2.5e-2, 'meannz': 6e-2, 'desc': 'focal diff', 'eps0': 100., 'eps1': .1}, + 't': {'mednz' : 1.1e-1, 'meannz': 2.7e-1, 'desc': 'trans diff', 'eps0': .25, 'eps1': .1}, + 'rt': {'mednz' : 8e-2, 'meannz': 1.8e-1, 'desc': 'rot diff', 'eps0': 0.02, 'eps1': .5}, + 'k': {'mednz' : 7e-2, 'meannz': 5.1e-1, 'desc': 'distortion diff', 'eps0': .5, 'eps1': .05} } for renderer in renderers: - im_shape = (renderer.frustum['height'], renderer.frustum['width'], 3) + im_shape = renderer.shape + lighting = lightings[renderer.num_channels] # Render a rotating mesh mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) @@ -184,13 +197,14 @@ def test_cam_derivatives(self): dr = renderer.dr_wrt(atr()) # Establish a random direction - direction = (np.random.rand(atr_size)-.5)*info['eps0'] + tmp = np.random.rand(atr().size) - .5 + direction = (tmp / np.linalg.norm(tmp))*info['eps0'] #direction = np.sin(np.ones(atr_size))*info['eps0'] #direction = np.zeros(atr_size) # try: # direction[4] = 1. # except: pass - direction *= info['eps0'] + #direction *= info['eps0'] eps = info['eps1'] # Render going forward in that direction @@ -208,12 +222,11 @@ def test_cam_derivatives(self): dr_empirical = (np.asarray(rfwd, np.float64) - np.asarray(rbwd, np.float64)).ravel() / eps dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) - images = { - 'shifted %s' % (atrname,) : np.asarray(rfwd, np.float64)-.5, - r'empirical %s' % (atrname,): dr_empirical, - r'predicted %s' % (atrname,): dr_predicted, - info['desc']: dr_predicted - dr_empirical - } + images = OrderedDict() + images['shifted %s' % (atrname,)] = np.asarray(rfwd, np.float64)-.5 + images[r'empirical %s' % (atrname,)] = dr_empirical + images[r'predicted %s' % (atrname,)] = dr_predicted + images[info['desc']] = dr_predicted - dr_empirical nonzero = images[info['desc']][np.nonzero(images[info['desc']]!=0)[0]] @@ -222,8 +235,8 @@ def test_cam_derivatives(self): if visualize: matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) - for idx, title in enumerate(sorted(images.keys(), reverse=True)): - plt.subplot(1,len(images.keys()), idx) + for idx, title in enumerate(images.keys()): + plt.subplot(1,len(images.keys()), idx+1) im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) @@ -235,15 +248,16 @@ def test_cam_derivatives(self): self.assertTrue(meanerror Date: Tue, 15 Jul 2014 19:06:22 -0400 Subject: [PATCH 04/56] lighting.py: added lambertian spotlight --- lighting.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lighting.py b/lighting.py index 11ebcba..6513f6c 100755 --- a/lighting.py +++ b/lighting.py @@ -141,6 +141,28 @@ def compute_dr_wrt(self, wrt): return gr_equal_zero.dot(result) +def lambertian_spotlight(v, vn, pos, dir, spot_exponent): + """ + :param v: vertices + :param vn: vertex normals + :param light_pos: light position + :param light_dir: light direction + :param spot_exponent: spot exponent (a la opengl) + :return: Vx1 array of brightness + """ + dir = dir / ch.sqrt(ch.sum(dir**2.)) + normalize_rows = lambda v : v / col(ch.sqrt(ch.sum(v.reshape((-1,3))**2, axis=1))) + v_minus_light_normed = normalize_rows(v - pos.reshape((1,3))) + cosangle = v_minus_light_normed.dot(dir.reshape((3,1))) + light_dot_normal = ch.sum(vn*v_minus_light_normed, axis=1) + light_dot_normal.label = 'light_dot_normal' + cosangle.label = 'cosangle' + result = light_dot_normal.ravel() * cosangle.ravel()**spot_exponent + return maximum(result, 0.0) + + + + class LambertianPointLight(Ch): terms = 'f', 'num_verts', 'light_color' From 8cc590fc38d9654841c3f675ade129ed5db7952b Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Fri, 18 Jul 2014 22:27:44 -0400 Subject: [PATCH 05/56] Add generated stuff in contexts to .gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 51cbe85..01d3041 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,10 @@ coverage.xml # Sphinx documentation docs/_build/ +contexts/OSMesa.Darwin.x86_64.zip +contexts/OSMesa/ +contexts/_constants.py +contexts/_functions.pyx +contexts/ctx_mac.c +contexts/ctx_mesa.c +venv \ No newline at end of file From 2c1b0edf4fed47b2cd16515c31d646729dfff731 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Fri, 18 Jul 2014 22:43:22 -0400 Subject: [PATCH 06/56] Switch to strict relative imports. Without this, if you had two versions of opendr installed, for example one that you're working on and an old one in site-packages, they could import each other, leaveing you with potentially inconsistent code that can be really hard to debug. --- camera.py | 2 +- common.py | 2 +- geometry.py | 2 +- lighting.py | 2 +- renderer.py | 14 +++++++------- serialization.py | 2 +- test_dr/common.py | 4 ++-- test_dr/test_camera.py | 2 +- test_dr/test_depth_renderer.py | 20 ++++++++++---------- test_dr/test_geometry.py | 4 ++-- test_dr/test_renderer.py | 8 ++++---- test_dr/test_sh.py | 12 ++++++------ 12 files changed, 37 insertions(+), 37 deletions(-) diff --git a/camera.py b/camera.py index 19153cf..d7b1d1b 100755 --- a/camera.py +++ b/camera.py @@ -15,7 +15,7 @@ import numpy as np import scipy.sparse as sp from chumpy.utils import row, col -from opendr.geometry import Rodrigues +from geometry import Rodrigues def RigidTransformSlow(**kwargs): # Returns a Ch object with dterms 'v', 'rt', and 't' diff --git a/common.py b/common.py index 951465d..448bf2d 100755 --- a/common.py +++ b/common.py @@ -13,7 +13,7 @@ import scipy.stats from chumpy.utils import row, col -from .contexts._constants import * +from contexts._constants import * def nanmean(a, axis): # don't call nan_to_num in here, unless you check that diff --git a/geometry.py b/geometry.py index 203db6e..f8ea09c 100755 --- a/geometry.py +++ b/geometry.py @@ -16,7 +16,7 @@ from chumpy import * import chumpy as ch from chumpy.ch import MatVecMult -from opendr.topology import get_faces_per_edge, get_vert_connectivity +from topology import get_faces_per_edge, get_vert_connectivity def volume(v, f): diff --git a/lighting.py b/lighting.py index 6513f6c..cb34be4 100755 --- a/lighting.py +++ b/lighting.py @@ -17,7 +17,7 @@ from chumpy.utils import row, col import chumpy as ch from chumpy.ch import Ch -from opendr.geometry import VertNormals +from geometry import VertNormals from chumpy import multiply, maximum diff --git a/renderer.py b/renderer.py index e0bbc93..35aef66 100755 --- a/renderer.py +++ b/renderer.py @@ -15,17 +15,17 @@ import platform import scipy.sparse as sp from copy import deepcopy -from . import common -from .common import draw_visibility_image, draw_barycentric_image, draw_colored_primitives, draw_texcoord_image -from .topology import get_vertices_per_edge, get_faces_per_edge +import common +from common import draw_visibility_image, draw_barycentric_image, draw_colored_primitives, draw_texcoord_image +from topology import get_vertices_per_edge, get_faces_per_edge if platform.system()=='Darwin': - from .contexts.ctx_mac import OsContext + from contexts.ctx_mac import OsContext else: - from .contexts.ctx_mesa import OsContext + from contexts.ctx_mesa import OsContext from chumpy import * -from .contexts._constants import * +from contexts._constants import * from chumpy.utils import row, col @@ -697,7 +697,7 @@ def draw_boundary_images(glf, glb, v, f, vpe, fpe, camera): def compute_vpe_boundary_idxs(v, f, camera, fpe): # Figure out which edges are on pairs of differently visible triangles - from opendr.geometry import TriNormals + from geometry import TriNormals tn = TriNormals(v, f).r.reshape((-1,3)) #ray = cv2.Rodrigues(camera.rt.r)[0].T[:,2] diff --git a/serialization.py b/serialization.py index 784953b..c1df241 100644 --- a/serialization.py +++ b/serialization.py @@ -11,7 +11,7 @@ from os.path import split, splitext, join, exists, normpath import cv2 import numpy as np -from opendr.dummy import Minimal +from dummy import Minimal def load_image(filename): diff --git a/test_dr/common.py b/test_dr/common.py index d5c9273..178a72f 100644 --- a/test_dr/common.py +++ b/test_dr/common.py @@ -6,10 +6,10 @@ import cv2 from chumpy.utils import row, col -from opendr.utils import wget +from utils import wget def get_earthmesh(trans, rotation): - from opendr.serialization import load_mesh + from serialization import load_mesh from copy import deepcopy if not hasattr(get_earthmesh, 'm'): diff --git a/test_dr/test_camera.py b/test_dr/test_camera.py index f3fbe83..5b0c7bb 100755 --- a/test_dr/test_camera.py +++ b/test_dr/test_camera.py @@ -9,7 +9,7 @@ import unittest import numpy as np -from opendr.camera import * +from camera import * import chumpy as ch diff --git a/test_dr/test_depth_renderer.py b/test_dr/test_depth_renderer.py index eb0ef27..841fafa 100644 --- a/test_dr/test_depth_renderer.py +++ b/test_dr/test_depth_renderer.py @@ -1,4 +1,4 @@ -from opendr.renderer import DepthRenderer +from renderer import DepthRenderer import numpy as np import unittest @@ -13,16 +13,16 @@ def setUp(self): def test_depth_image(self): # Create renderer import chumpy as ch - from opendr.renderer import DepthRenderer + from renderer import DepthRenderer rn = DepthRenderer() # Assign attributes to renderer - from opendr.test_dr.common import get_earthmesh + from test_dr.common import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,0]), rotation=ch.zeros(3)) m.v = m.v * .01 m.v[:,2] += 4 w, h = (320, 240) - from opendr.camera import ProjectPoints + from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3)) @@ -42,15 +42,15 @@ def test_derivatives(self): import chumpy as ch from chumpy.utils import row import numpy as np - from opendr.renderer import DepthRenderer + from renderer import DepthRenderer rn = DepthRenderer() # Assign attributes to renderer - from opendr.test_dr.common import get_earthmesh + from test_dr.common import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) - from opendr.camera import ProjectPoints + from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) @@ -87,15 +87,15 @@ def test_derivatives(self): def test_derivatives2(self): import chumpy as ch import numpy as np - from opendr.renderer import DepthRenderer + from renderer import DepthRenderer rn = DepthRenderer() # Assign attributes to renderer - from opendr.test_dr.common import get_earthmesh + from test_dr.common import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) - from opendr.camera import ProjectPoints + from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) diff --git a/test_dr/test_geometry.py b/test_dr/test_geometry.py index f1da95b..6540c36 100755 --- a/test_dr/test_geometry.py +++ b/test_dr/test_geometry.py @@ -20,7 +20,7 @@ def setUp(self): np.random.seed(0) def test_rodrigues(self): - from opendr.geometry import Rodrigues + from geometry import Rodrigues rt = np.random.randn(3) rt2 = rt + np.random.rand(3)*1e-5 foo1 = Rodrigues(rt = rt) @@ -33,7 +33,7 @@ def test_rodrigues(self): def test_vert_normals(self): - from opendr.geometry import VertNormals + from geometry import VertNormals import numpy as np mesh = get_earthmesh(np.zeros(3), np.zeros(3)) diff --git a/test_dr/test_renderer.py b/test_dr/test_renderer.py index f90528d..ffbc4f5 100755 --- a/test_dr/test_renderer.py +++ b/test_dr/test_renderer.py @@ -17,11 +17,11 @@ except: from dummy import dummy as plt -from opendr.renderer import * +from renderer import * from chumpy import Ch from chumpy.utils import row, col -from opendr.lighting import * -from opendr.test_dr.common import get_earthmesh, process +from lighting import * +from test_dr.common import get_earthmesh, process from collections import OrderedDict @@ -29,7 +29,7 @@ visualize = False def getcam(): - from opendr.camera import ProjectPoints + from camera import ProjectPoints w = 256 h = 192 diff --git a/test_dr/test_sh.py b/test_dr/test_sh.py index 286cc0e..f19a4f4 100755 --- a/test_dr/test_sh.py +++ b/test_dr/test_sh.py @@ -9,18 +9,18 @@ from chumpy import Ch import numpy as np from chumpy.utils import row, col -from opendr.lighting import SphericalHarmonics +from lighting import SphericalHarmonics import unittest try: import matplotlib.pyplot as plt except: from dummy import dummy as plt -from opendr.topology import loop_subdivider +from topology import loop_subdivider visualize = False def getcam(): - from opendr.camera import ProjectPoints3D + from camera import ProjectPoints3D w = 640 h = 320 @@ -50,7 +50,7 @@ def test_spherical_harmonics(self): # Get mesh v, f = get_sphere_mesh() - from opendr.geometry import VertNormals + from geometry import VertNormals vn = VertNormals(v=v, f=f) #vn = Ch(mesh.estimate_vertex_normals()) @@ -58,7 +58,7 @@ def test_spherical_harmonics(self): cam, frustum = getcam() # Get renderer - from opendr.renderer import ColoredRenderer + from renderer import ColoredRenderer cam.v = v cr = ColoredRenderer(f=f, camera=cam, frustum=frustum, v=v) @@ -130,7 +130,7 @@ def test_spherical_harmonics(self): def get_sphere_mesh(): - from opendr.test_dr.common import get_earthmesh + from test_dr.common import get_earthmesh mesh = get_earthmesh(np.zeros(3), np.zeros(3)) # load_mesh(filename) v, f = mesh.v*64., mesh.f From b291e06a505a908ef05cbec04782b9b2e4b1e18d Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Sat, 19 Jul 2014 10:28:31 -0400 Subject: [PATCH 07/56] Replaced "assertTrue" with "assertGreater"/"assertLess" so we know how badly we are failing --- test_dr/test_camera.py | 4 ++-- test_dr/test_depth_renderer.py | 10 +++++----- test_dr/test_renderer.py | 24 ++++++++++++------------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test_dr/test_camera.py b/test_dr/test_camera.py index 5b0c7bb..63178f9 100755 --- a/test_dr/test_camera.py +++ b/test_dr/test_camera.py @@ -63,8 +63,8 @@ def project_points(self, cls): # print 'max diff: %.2e' % (max_diff,) #print 'pct diff: %.2e%%' % (pct_diff,) - self.assertTrue(med_diff < 1e-8) - self.assertTrue(max_diff < 5e-8) + self.assertLess(med_diff, 1e-8) + self.assertLess(max_diff, 5e-8) pp_dist = cls(**cam_params) diff --git a/test_dr/test_depth_renderer.py b/test_dr/test_depth_renderer.py index 841fafa..3b29948 100644 --- a/test_dr/test_depth_renderer.py +++ b/test_dr/test_depth_renderer.py @@ -34,9 +34,9 @@ def test_depth_image(self): # print np.min(rn.r.ravel()) # print np.max(rn.r.ravel()) - self.assertTrue(np.abs(np.min(rn.r.ravel()) - 3.98) < 1e-5) - self.assertTrue(np.abs(np.min(m.v[:,2]) - np.min(rn.r.ravel())) < 1e-5) - self.assertTrue(np.abs(rn.r[h/2,w/2] - 3.98) < 1e-5) + self.assertLess(np.abs(np.min(rn.r.ravel()) - 3.98), 1e-5) + self.assertLess(np.abs(np.min(m.v[:,2]) - np.min(rn.r.ravel())), 1e-5) + self.assertLess(np.abs(rn.r[h/2,w/2] - 3.98), 1e-5) def test_derivatives(self): import chumpy as ch @@ -72,7 +72,7 @@ def test_derivatives(self): # print np.mean(np.abs(dr_pred-dr_emp)) - self.assertTrue(np.mean(np.abs(dr_pred-dr_emp)) < .025) + self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .025) if visualize: plt.subplot(2,3,which+1) @@ -118,7 +118,7 @@ def test_derivatives2(self): #print np.mean(np.abs(dr_pred-dr_emp)) - self.assertTrue(np.mean(np.abs(dr_pred-dr_emp)) < .019) + self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .019) if visualize: plt.subplot(2,3,which+1) diff --git a/test_dr/test_renderer.py b/test_dr/test_renderer.py index ffbc4f5..7d4e27c 100755 --- a/test_dr/test_renderer.py +++ b/test_dr/test_renderer.py @@ -124,10 +124,10 @@ def test_distortion(self): d1 = d1[d1 != 0.] d2 = d2[d2 != 0.] - self.assertTrue(np.mean(d1**2) / np.mean(d2**2) > 44.) - self.assertTrue(np.mean(d2**2)<0.0016) - self.assertTrue(np.median(d1**2) / np.median(d2**2) > 650) - self.assertTrue(np.median(d2**2) < 1.9e-5) + self.assertGreater(np.mean(d1**2) / np.mean(d2**2), 44.) + self.assertLess(np.mean(d2**2), 0.0016) + self.assertGreater(np.median(d1**2) / np.median(d2**2), 650) + self.assertLess(np.median(d2**2), 1.9e-5) if visualize: @@ -246,8 +246,8 @@ def test_cam_derivatives(self): plt.draw() plt.show() - self.assertTrue(meanerror Date: Sat, 19 Jul 2014 10:36:33 -0400 Subject: [PATCH 08/56] loosened unit tests slightly for linux --- test_dr/test_depth_renderer.py | 4 ++-- test_dr/test_renderer.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test_dr/test_depth_renderer.py b/test_dr/test_depth_renderer.py index 3b29948..6902c4c 100644 --- a/test_dr/test_depth_renderer.py +++ b/test_dr/test_depth_renderer.py @@ -72,7 +72,7 @@ def test_derivatives(self): # print np.mean(np.abs(dr_pred-dr_emp)) - self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .025) + self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .026) if visualize: plt.subplot(2,3,which+1) @@ -118,7 +118,7 @@ def test_derivatives2(self): #print np.mean(np.abs(dr_pred-dr_emp)) - self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .019) + self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .021) if visualize: plt.subplot(2,3,which+1) diff --git a/test_dr/test_renderer.py b/test_dr/test_renderer.py index 7d4e27c..1b01785 100755 --- a/test_dr/test_renderer.py +++ b/test_dr/test_renderer.py @@ -164,9 +164,9 @@ def test_cam_derivatives(self): mesh, lightings, camera, frustum, renderers = self.load_basics() camparms = { - 'c': {'mednz' : 1.9e-2, 'meannz': 4.0e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, + 'c': {'mednz' : 2.2e-2, 'meannz': 4.0e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, #'f': {'mednz' : 2.5e-2, 'meannz': 6e-2, 'desc': 'focal diff', 'eps0': 100., 'eps1': .1}, - 't': {'mednz' : 1.1e-1, 'meannz': 2.7e-1, 'desc': 'trans diff', 'eps0': .25, 'eps1': .1}, + 't': {'mednz' : 1.2e-1, 'meannz': 2.8e-1, 'desc': 'trans diff', 'eps0': .25, 'eps1': .1}, 'rt': {'mednz' : 8e-2, 'meannz': 1.8e-1, 'desc': 'rot diff', 'eps0': 0.02, 'eps1': .5}, 'k': {'mednz' : 7e-2, 'meannz': 5.1e-1, 'desc': 'distortion diff', 'eps0': .5, 'eps1': .05} } From 12b544ed2b2444f36b94bca6d0df7c35318f8f76 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Sat, 19 Jul 2014 11:14:44 -0400 Subject: [PATCH 09/56] more loosening of unit tests for linux --- test_dr/test_renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_dr/test_renderer.py b/test_dr/test_renderer.py index 1b01785..3465e1c 100755 --- a/test_dr/test_renderer.py +++ b/test_dr/test_renderer.py @@ -164,7 +164,7 @@ def test_cam_derivatives(self): mesh, lightings, camera, frustum, renderers = self.load_basics() camparms = { - 'c': {'mednz' : 2.2e-2, 'meannz': 4.0e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, + 'c': {'mednz' : 2.2e-2, 'meannz': 4.1e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, #'f': {'mednz' : 2.5e-2, 'meannz': 6e-2, 'desc': 'focal diff', 'eps0': 100., 'eps1': .1}, 't': {'mednz' : 1.2e-1, 'meannz': 2.8e-1, 'desc': 'trans diff', 'eps0': .25, 'eps1': .1}, 'rt': {'mednz' : 8e-2, 'meannz': 1.8e-1, 'desc': 'rot diff', 'eps0': 0.02, 'eps1': .5}, From 0ff6c800d645b5e9e1237bb79612083c3f34b72f Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Tue, 22 Jul 2014 15:22:54 -0400 Subject: [PATCH 10/56] lighting.py: added camcoord option for lambertian spotlight --- lighting.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lighting.py b/lighting.py index cb34be4..d1df3c6 100755 --- a/lighting.py +++ b/lighting.py @@ -141,24 +141,39 @@ def compute_dr_wrt(self, wrt): return gr_equal_zero.dot(result) -def lambertian_spotlight(v, vn, pos, dir, spot_exponent): +def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_t=None, camera_rt=None): """ :param v: vertices :param vn: vertex normals :param light_pos: light position :param light_dir: light direction :param spot_exponent: spot exponent (a la opengl) + :param camcoord: if True, then pos and dir are wrt the camera + :param camera_t: 3-vector indicating translation of camera + :param camera_rt: 3-vector indicating direction of camera :return: Vx1 array of brightness """ + + if camcoord: # Transform pos and dir from camera to world coordinate system + assert(camera_t is not None and camera_rt is not None) + from opendr.geometry import Rodrigues + rot = Rodrigues(rt=camera_rt) + pos = rot.T.dot(pos-camera_t) + dir = rot.T.dot(dir) + dir = dir / ch.sqrt(ch.sum(dir**2.)) - normalize_rows = lambda v : v / col(ch.sqrt(ch.sum(v.reshape((-1,3))**2, axis=1))) - v_minus_light_normed = normalize_rows(v - pos.reshape((1,3))) + v_minus_light = v - pos.reshape((1,3)) + v_distances = ch.sqrt(ch.sum(v_minus_light**2, axis=1)) + v_minus_light_normed = v_minus_light / v_distances.reshape((-1,1)) cosangle = v_minus_light_normed.dot(dir.reshape((3,1))) light_dot_normal = ch.sum(vn*v_minus_light_normed, axis=1) light_dot_normal.label = 'light_dot_normal' cosangle.label = 'cosangle' result = light_dot_normal.ravel() * cosangle.ravel()**spot_exponent - return maximum(result, 0.0) + result = result / v_distances ** 2. + result = maximum(result, 0.0) + + return result From 31bbe1d98431d0afa2e9623cc39af75990646cc4 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Mon, 28 Jul 2014 16:59:49 -0400 Subject: [PATCH 11/56] topology.py: support non-watertight meshes --- topology.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/topology.py b/topology.py index 4c5bc94..40a099b 100644 --- a/topology.py +++ b/topology.py @@ -152,12 +152,10 @@ def loop_subdivider(mesh_v, mesh_f): data.append(3./8) opposites = vo[(vsl[0], vsl[1])] - IS.append(start + idx) - IS.append(start + idx) - JS.append(opposites[0]) - JS.append(opposites[1]) - data.append(1./8) - data.append(1./8) + for opp in opposites: + IS.append(start + idx) + JS.append(opp) + data.append(2./8./len(opposites)) edge_to_midpoint[(vsl[0], vsl[1])] = start + idx edge_to_midpoint[(vsl[1], vsl[0])] = start + idx From a2373a8285bb1f152112ee64b9b48c7474467475 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Mon, 28 Jul 2014 22:19:29 -0400 Subject: [PATCH 12/56] util_tests.py: fixed for __array_priority__ change --- test_dr/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_dr/common.py b/test_dr/common.py index 178a72f..ff5c553 100644 --- a/test_dr/common.py +++ b/test_dr/common.py @@ -34,7 +34,7 @@ def wg(url): mesh = deepcopy(get_earthmesh.mesh) mesh.v = mesh.v.dot(cv2.Rodrigues(np.asarray(np.array(rotation), np.float64))[0]) - mesh.v = mesh.v + row(trans) + mesh.v = mesh.v + row(np.asarray(trans)) return mesh From 90025c0b89e701ff6ac88c50f5424fc337fa92e0 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 03:51:06 -0400 Subject: [PATCH 13/56] Added fields to setup (like "description") and added README.txt --- README.txt | 16 ++++++++++++++++ setup.py | 5 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 README.txt diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..465c6bf --- /dev/null +++ b/README.txt @@ -0,0 +1,16 @@ +The OpenDR (or Open Differentiable Renderer) can be used for rendering and optimisation to image evidence. + +- Rendering is achieved by constructing and initialising one of the renderers available in OpenDR. +- Optimization is achieved by minimising an objective that includes a renderer. + +OpenDR is useful even without optimisation: if you just wish to animate meshes over time without performing optimisation, OpenDR may still be a good choice for rendering those meshes to images offscreen, for later compilation into a movie. + +OpenDR is also designed to be concise: it should not take many lines of code to construct a scene. Although it will not replace dedicated commercial platforms (such as Maya) for some tasks, it is flexible enough for many tasks, and in some cases goes beyond what Maya can offer. + +OpenDR comes with its own demos, which can be seen by typing the following: + +>> import opendr +>> opendr.demo() # prints out a list of possible demos + +Licensing is specified in the attached LICENSE.txt. + diff --git a/setup.py b/setup.py index 77fbb41..02ab806 100644 --- a/setup.py +++ b/setup.py @@ -53,15 +53,16 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.5', + version='0.51', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', author_email = 'matt.loper@gmail.com', - url = 'http://files.is.tue.mpg/mloper/opendr/', + url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, install_requires=['cython'], + description='opendr', ext_modules=ext_modules, ) From 03df9d11449ad9c0879adf511b1eb18908dd8a19 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 03:53:07 -0400 Subject: [PATCH 14/56] Makefile: added upload option --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ded68e6..06b187a 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,11 @@ all: python2.7 setup.py build_ext --inplace -sdist: all - python setup.py sdist && rsync -avz dist/opendr-0.5.tar.gz files:~/opendr/latest.tgz +upload: + python setup.py register sdist upload + +#sdist: all +# python setup.py sdist && rsync -avz dist/opendr-0.5.tar.gz files:~/opendr/latest.tgz clean: rm -rf `find . -name \*.pyc` `find . -name \*~` build/ dist/; make -C contexts clean From 39667cdce61e8a5d2ec41ed7f9a41c096a2310c9 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 04:04:50 -0400 Subject: [PATCH 15/56] setup.py: require chumpy >= .51 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 02ab806..0ee55cb 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.51', + version='0.52', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', @@ -61,7 +61,7 @@ def setup_opendr(ext_modules): url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - install_requires=['cython'], + install_requires=['cython', 'chumpy >= 0.51'], description='opendr', ext_modules=ext_modules, ) From a0aa109296009e2cb508b7baf4d6942560a26a41 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 04:48:48 -0400 Subject: [PATCH 16/56] Attempt to fix cythonize problems for pip install --- MANIFEST.in | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index ade7437..b6639cd 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -global-include . *.py *.c *.h Makefile nasa* +global-include . *.py *.c *.h Makefile nasa* *.pyx prune contexts/OSMesa global-exclude . rogrenderer* diff --git a/setup.py b/setup.py index 0ee55cb..83073fd 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.52', + version='0.53', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', From e47a8a0816e53afeb7768c0e111e672784cb1708 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 05:18:56 -0400 Subject: [PATCH 17/56] Moved tests into main dir, to get rid of relative import madness. --- __init__.py | 16 ++++++++-------- test_dr/occlusion_test.py => occlusion_test.py | 4 ++-- test_dr/slider_demo.py => slider_demo.py | 0 test_dr/test_camera.py => test_camera.py | 0 ...t_depth_renderer.py => test_depth_renderer.py | 6 +++--- test_dr/test_geometry.py => test_geometry.py | 2 +- test_dr/test_renderer.py => test_renderer.py | 2 +- test_dr/test_sh.py => test_sh.py | 2 +- test_dr/common.py => util_tests.py | 0 9 files changed, 16 insertions(+), 16 deletions(-) rename test_dr/occlusion_test.py => occlusion_test.py (97%) rename test_dr/slider_demo.py => slider_demo.py (100%) rename test_dr/test_camera.py => test_camera.py (100%) rename test_dr/test_depth_renderer.py => test_depth_renderer.py (96%) rename test_dr/test_geometry.py => test_geometry.py (97%) rename test_dr/test_renderer.py => test_renderer.py (99%) rename test_dr/test_sh.py => test_sh.py (99%) rename test_dr/common.py => util_tests.py (100%) diff --git a/__init__.py b/__init__.py index 6a7a04d..1651cd5 100644 --- a/__init__.py +++ b/__init__.py @@ -17,7 +17,7 @@ def test(): rn = TexturedRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints @@ -35,7 +35,7 @@ def test(): """ demos['moments'] = """ -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh from opendr.simple import * import numpy as np @@ -83,7 +83,7 @@ def test(): rn = ColoredRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) @@ -122,7 +122,7 @@ def test(): rn = ColoredRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints @@ -146,7 +146,7 @@ def test(): rn = BoundaryRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints @@ -171,7 +171,7 @@ def test(): rn = ColoredRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) @@ -208,7 +208,7 @@ def test(): rn = ColoredRenderer() # Assign attributes to renderer -from opendr.test_dr.common import get_earthmesh +from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints @@ -240,7 +240,7 @@ def test(): try: m = load_mesh('earth.obj') except: - from opendr.test_dr.common import get_earthmesh + from opendr.util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) # Create V, A, U, f: geometry, brightness, camera, renderer diff --git a/test_dr/occlusion_test.py b/occlusion_test.py similarity index 97% rename from test_dr/occlusion_test.py rename to occlusion_test.py index c52ea20..aa1498c 100644 --- a/test_dr/occlusion_test.py +++ b/occlusion_test.py @@ -22,7 +22,7 @@ def test_occlusion(self): rn = ColoredRenderer() # Assign attributes to renderer - from opendr.test_dr.common import get_earthmesh + from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) rn.texture_image = m.texture_image rn.ft = m.ft @@ -137,4 +137,4 @@ def test_occlusion(self): visualize = True suite = unittest.TestLoader().loadTestsFromTestCase(TestOcclusion) unittest.TextTestRunner(verbosity=2).run(suite) - import pdb; pdb.set_trace() \ No newline at end of file + import pdb; pdb.set_trace() diff --git a/test_dr/slider_demo.py b/slider_demo.py similarity index 100% rename from test_dr/slider_demo.py rename to slider_demo.py diff --git a/test_dr/test_camera.py b/test_camera.py similarity index 100% rename from test_dr/test_camera.py rename to test_camera.py diff --git a/test_dr/test_depth_renderer.py b/test_depth_renderer.py similarity index 96% rename from test_dr/test_depth_renderer.py rename to test_depth_renderer.py index 6902c4c..90c7fd4 100644 --- a/test_dr/test_depth_renderer.py +++ b/test_depth_renderer.py @@ -17,7 +17,7 @@ def test_depth_image(self): rn = DepthRenderer() # Assign attributes to renderer - from test_dr.common import get_earthmesh + from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,0]), rotation=ch.zeros(3)) m.v = m.v * .01 m.v[:,2] += 4 @@ -47,7 +47,7 @@ def test_derivatives(self): rn = DepthRenderer() # Assign attributes to renderer - from test_dr.common import get_earthmesh + from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from camera import ProjectPoints @@ -92,7 +92,7 @@ def test_derivatives2(self): rn = DepthRenderer() # Assign attributes to renderer - from test_dr.common import get_earthmesh + from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) w, h = (320, 240) from camera import ProjectPoints diff --git a/test_dr/test_geometry.py b/test_geometry.py similarity index 97% rename from test_dr/test_geometry.py rename to test_geometry.py index 6540c36..0a524c5 100755 --- a/test_dr/test_geometry.py +++ b/test_geometry.py @@ -12,7 +12,7 @@ import chumpy as ch from chumpy import Ch import numpy as np -from common import get_earthmesh +from util_tests import get_earthmesh class TestGeometry(unittest.TestCase): diff --git a/test_dr/test_renderer.py b/test_renderer.py similarity index 99% rename from test_dr/test_renderer.py rename to test_renderer.py index 3465e1c..426ae42 100755 --- a/test_dr/test_renderer.py +++ b/test_renderer.py @@ -21,7 +21,7 @@ from chumpy import Ch from chumpy.utils import row, col from lighting import * -from test_dr.common import get_earthmesh, process +from util_tests import get_earthmesh, process from collections import OrderedDict diff --git a/test_dr/test_sh.py b/test_sh.py similarity index 99% rename from test_dr/test_sh.py rename to test_sh.py index f19a4f4..6b789e1 100755 --- a/test_dr/test_sh.py +++ b/test_sh.py @@ -130,7 +130,7 @@ def test_spherical_harmonics(self): def get_sphere_mesh(): - from test_dr.common import get_earthmesh + from util_tests import get_earthmesh mesh = get_earthmesh(np.zeros(3), np.zeros(3)) # load_mesh(filename) v, f = mesh.v*64., mesh.f diff --git a/test_dr/common.py b/util_tests.py similarity index 100% rename from test_dr/common.py rename to util_tests.py From cb9d4b7a926dfef8bb3ae96e98fb415441bfa19f Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 05:27:20 -0400 Subject: [PATCH 18/56] Incremented version for pipy upload. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 83073fd..25a5c72 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.53', + version='0.54', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', From 369d6abb95e168ab9aa3b13440175174f37e73ce Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 05:40:48 -0400 Subject: [PATCH 19/56] renderer.py: Added overdraw=True as default for BoundaryRenderer --- renderer.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/renderer.py b/renderer.py index 35aef66..57ed65f 100755 --- a/renderer.py +++ b/renderer.py @@ -293,10 +293,9 @@ def on_changed(self, which): setup_camera(self.glb, self.camera, self.frustum) setup_camera(self.glf, self.camera, self.frustum) - - - - + if not hasattr(self, 'overdraw'): + self.overdraw = True + @depends_on(terms+dterms) def color_image(self): self._call_on_changed() From 2286686b41074ef7b1846e19a8acbf2c6cfae894 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Wed, 23 Jul 2014 05:41:19 -0400 Subject: [PATCH 20/56] setup.py: incremented version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 25a5c72..3970de3 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.54', + version='0.55', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', From 8963b58be41620b6090cb2a81a616f4b58f3ace2 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Fri, 25 Jul 2014 01:17:14 -0400 Subject: [PATCH 21/56] added matplotlib as a req, so that demos will run. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 3970de3..f0d328b 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.55', + version='0.56', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', @@ -61,7 +61,7 @@ def setup_opendr(ext_modules): url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - install_requires=['cython', 'chumpy >= 0.51'], + install_requires=['cython', 'chumpy >= 0.51', 'matplotlib'], description='opendr', ext_modules=ext_modules, ) From 15d5a330e727e32204d31bac0a5de8c9e2e02608 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Sat, 26 Jul 2014 18:23:48 -0400 Subject: [PATCH 22/56] setup.py: added more information for pypi --- setup.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f0d328b..1d25dda 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.56', + version='0.57', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', @@ -61,9 +61,35 @@ def setup_opendr(ext_modules): url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - install_requires=['cython', 'chumpy >= 0.51', 'matplotlib'], + install_requires=['cython', 'chumpy >= 0.53', 'matplotlib'], description='opendr', ext_modules=ext_modules, + license='MIT', + + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 4 - Beta', + + # Indicate who your project is intended for + 'Intended Audience :: Science/Research', + 'Topic :: Multimedia :: Graphics :: 3D Rendering', + + # Pick your license as you wish (should match "license" above) + 'License :: OSI Approved :: MIT License', + + # Specify the Python versions you support here. In particular, ensure + # that you indicate whether you support Python 2, Python 3 or both. + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: POSIX :: Linux' + ], + ) From a08f98cc15e5c28ab455aef9207218e2205fc450 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Sat, 26 Jul 2014 18:25:10 -0400 Subject: [PATCH 23/56] README.txt: fixed some markdown --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 465c6bf..7ece74f 100644 --- a/README.txt +++ b/README.txt @@ -7,7 +7,7 @@ OpenDR is useful even without optimisation: if you just wish to animate meshes o OpenDR is also designed to be concise: it should not take many lines of code to construct a scene. Although it will not replace dedicated commercial platforms (such as Maya) for some tasks, it is flexible enough for many tasks, and in some cases goes beyond what Maya can offer. -OpenDR comes with its own demos, which can be seen by typing the following: +OpenDR comes with its own demos, which can be seen by typing the following:: >> import opendr >> opendr.demo() # prints out a list of possible demos From b5637e1c3d42e606c5544bf02f56b4127b06b771 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Tue, 26 Aug 2014 10:18:29 -0400 Subject: [PATCH 24/56] Don't compile mesa on mac, add cvwrap in case opencv isn't available, tolerate lack of cython, and added normalization option to VertNormals. --- cvwrap.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cvwrap.py diff --git a/cvwrap.py b/cvwrap.py new file mode 100644 index 0000000..b6e38e4 --- /dev/null +++ b/cvwrap.py @@ -0,0 +1,4 @@ +try: + import cv2 +except: + raise Exception('Failed to import cv2 from the OpenCV distribution. Please install OpenCV with Python support. OpenCV may either be installed from http://opencv.org or installed with package managers such as Homebrew (on Mac, http://brew.sh) or apt-get (on Ubuntu or Debian).') \ No newline at end of file From 2880eae1468cbb86f45750426eed83ea82b501d0 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Tue, 26 Aug 2014 10:32:38 -0400 Subject: [PATCH 25/56] Actually do what I meant to do in last commit --- __init__.py | 24 +++++++++++++++--------- camera.py | 27 +++++++-------------------- common.py | 2 +- filters.py | 5 ++--- geometry.py | 40 ++++++++++++++++++++-------------------- renderer.py | 2 +- serialization.py | 2 +- setup.py | 23 ++++++++++++++++------- 8 files changed, 63 insertions(+), 62 deletions(-) diff --git a/__init__.py b/__init__.py index 1651cd5..fa09693 100644 --- a/__init__.py +++ b/__init__.py @@ -246,7 +246,7 @@ def test(): # 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.,1.,0.,0.,0.,0.,0.,0.,0.], + components=[3.,2.,0.,0.,0.,0.,0.,0.,0.], light_color=ch.ones(3)) U = ProjectPoints(v=V, f=[300,300.], c=[w/2.,h/2.], k=ch.zeros(5), t=ch.zeros(3), rt=ch.zeros(3)) @@ -258,16 +258,15 @@ def test(): translation, rotation = ch.array([0,0,4]), ch.zeros(3) f.v = translation + V.dot(Rodrigues(rotation)) -try: - observed = load_image('earth_observed.jpg') -except: - observed = f.r - translation[:] = translation.r + np.random.rand(3)*.25 - rotation[:] = rotation.r + np.random.rand(3)*.25 +observed = f.r +translation[:] = translation.r + np.random.rand(3)*.2 +rotation[:] = rotation.r + np.random.rand(3)*.2 +A.components[1:] = 0 # Create the energy difference = f - observed -E = gaussian_pyramid(difference, n_levels=6, normalization='SSE') +E = gaussian_pyramid(difference, n_levels=6, as_list=True)[-3:] +E = ch.concatenate([e.ravel() for e in E]) plt.ion() global cb @@ -276,6 +275,7 @@ def test(): def cb(_): plt.imshow(np.abs(difference.r)) + plt.title('Absolute difference') plt.draw() @@ -283,8 +283,14 @@ def cb(_): light_parms = A.components print 'OPTIMIZING TRANSLATION' ch.minimize({'energy': E}, x0=[translation], callback=lambda _ : cb(difference)) -print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' + +print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS (coarse)' ch.minimize({'energy': E}, x0=[translation, rotation, light_parms], callback=cb) + +print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS (refined)' +E = gaussian_pyramid(difference, n_levels=6, normalization='size') +ch.minimize({'energy': E}, x0=[translation, rotation, light_parms], callback=cb) + """ diff --git a/camera.py b/camera.py index d7b1d1b..c6cd4e6 100755 --- a/camera.py +++ b/camera.py @@ -11,7 +11,7 @@ import chumpy as ch from chumpy import depends_on, Ch -import cv2 +from cvwrap import cv2 import numpy as np import scipy.sparse as sp from chumpy.utils import row, col @@ -107,31 +107,18 @@ def compute_dr_wrt(self, wrt): def unproject_points(self, uvd, camera_space=False): cam = ProjectPoints3D(**{k: getattr(self, k) for k in self.dterms if hasattr(self, k)}) - if False: # slow way, probably not so good - cam.v = np.ones_like(uvd) - ch.minimize(cam - uvd, x0=[cam.v], method='dogleg', options={'disp': 0}) - result = cam.v.r - else: - try: - xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2)).copy()), np.asarray(cam.camera_mtx), cam.k.r) - except AttributeError: - import cv - num_row, num_col = uvd[:,:2].reshape((1,-1,2)).shape[0:2] - xy_undistorted_camspace_mat = cv.CreateMat(num_row, num_col, cv.CV_64FC2) - dist = cv.CreateMat(1, 5, cv.CV_32FC1) - for idx in range(cam.k.r.size): - dist[0, idx] = cam.k.r[idx] - cv.UndistortPoints(cv.fromarray(np.asarray(uvd[:,:2].reshape((1,-1,2))).copy()), - xy_undistorted_camspace_mat, - cv.fromarray(np.asarray(cam.camera_mtx)), - dist) - xy_undistorted_camspace = np.asarray(xy_undistorted_camspace_mat) + try: + xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2)).copy()), np.asarray(cam.camera_mtx), cam.k.r) xyz_camera_space = np.hstack((xy_undistorted_camspace.squeeze(), col(uvd[:,2]))) xyz_camera_space[:,:2] *= col(xyz_camera_space[:,2]) # scale x,y by z if camera_space: return xyz_camera_space other_answer = xyz_camera_space - row(cam.view_mtx[:,3]) # translate result = other_answer.dot(cam.view_mtx[:,:3]) # rotate + except: # slow way, probably not so good. But doesn't require cv2.undistortPoints. + cam.v = np.ones_like(uvd) + ch.minimize(cam - uvd, x0=[cam.v], method='dogleg', options={'disp': 0}) + result = cam.v.r return result def unproject_depth_image(self, depth_image, camera_space=False): diff --git a/common.py b/common.py index 448bf2d..beadaba 100755 --- a/common.py +++ b/common.py @@ -9,7 +9,7 @@ import numpy as np from copy import deepcopy import scipy.sparse as sp -import cv2 +from cvwrap import cv2 import scipy.stats from chumpy.utils import row, col diff --git a/filters.py b/filters.py index 9a9bb3d..bc0f1f9 100755 --- a/filters.py +++ b/filters.py @@ -8,7 +8,7 @@ __all__ = ['gaussian_pyramid', 'laplacian_pyramid'] -import cv2 +from cvwrap import cv2 import chumpy as ch import numpy as np from copy import deepcopy @@ -70,7 +70,6 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape) cur_imshape = cur_obj.output_shape output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label,ik)) - if not as_list: andit = lambda a : reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), a) @@ -80,7 +79,7 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level def GaussianKernel2D(ksize, sigma): if ksize % 2 != 1: - raise Exception('ksize should be an even number') + raise Exception('ksize should be an odd number') if sigma <= 0: raise Exception('sigma should be positive') oneway = np.tile(cv2.getGaussianKernel(ksize,sigma), (1, ksize)) diff --git a/geometry.py b/geometry.py index f8ea09c..7769ec9 100755 --- a/geometry.py +++ b/geometry.py @@ -7,9 +7,9 @@ See LICENCE.txt for licensing and contact information. """ -__all__ = ['Rodrigues', 'VertNormals', 'VertNormalsScaled', 'TriNormals', 'TriNormalsScaled', 'CrossProduct', 'TriArea', 'AcosTriAngles', 'volume'] +__all__ = ['Rodrigues', 'VertNormals', 'TriNormals', 'TriNormalsScaled', 'CrossProduct', 'TriArea', 'AcosTriAngles', 'volume'] -import cv2 +from cvwrap import cv2 import numpy as np import scipy.sparse as sp from chumpy.utils import row, col @@ -242,12 +242,17 @@ def AcosTriAngles(v, f, normalize): class VertNormals(Ch): + """If normalized==True, normals are normalized; otherwise they'll be about as long as neighboring edges.""" + dterms = 'v' - terms = 'f' + terms = 'f' 'normalized' term_order = 'v', 'f' def on_changed(self, which): + if not hasattr(self, 'normalized'): + self.normalized = True + for w in which: if w not in ('v', 'f'): raise Exception('VertNormals has only v and f now, and you specified %s.' % (w)) @@ -271,7 +276,18 @@ def on_changed(self, which): self.tns = Ch(lambda v : CrossProduct(TriEdges(f,1,0,v), TriEdges(f,2,0, v))) self.tns.v = self.v - self.normals = NormalizedNx3(MatVecMult(self.faces_by_vertex, self.tns)) + + if self.normalized: + tmp = MatVecMult(self.faces_by_vertex, self.tns) + self.normals = NormalizedNx3(tmp) + else: + test = self.faces_by_vertex.dot(np.ones(self.faces_by_vertex.shape[1])) + faces_by_vertex = sp.diags([1. / test], [0]).dot(self.faces_by_vertex).tocsc() + normals = MatVecMult(faces_by_vertex, self.tns).reshape((-1,3)) + normals = normals / (ch.sum(normals**2, axis=1) ** .25).reshape((-1,1)) + self.normals = normals + + def compute_r(self): return self.normals.r.reshape((-1,3)) @@ -282,22 +298,6 @@ def compute_dr_wrt(self, wrt): -def VertNormalsScaled(v, f): - IS = f.ravel() - JS = np.array([range(f.shape[0])]*3).T.ravel() - data = np.ones(len(JS)) - - IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) - JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) # is this right? - data = np.concatenate((data, data, data)) - - sz = v.r.size if hasattr(v, 'r') else v.size - faces_by_vertex = sp.csc_matrix((data, (IS, JS)), shape=(sz, f.size)) - - # faces_by_vertex should be 3 x wider...? - return NormalizedNx3(MatVecMult(faces_by_vertex, TriNormalsScaled(v, f))) - - def TriNormals(v, f): return NormalizedNx3(TriNormalsScaled(v,f)) diff --git a/renderer.py b/renderer.py index 57ed65f..6129ac1 100755 --- a/renderer.py +++ b/renderer.py @@ -10,7 +10,7 @@ __all__ = ['ColoredRenderer', 'TexturedRenderer', 'DepthRenderer'] import numpy as np -import cv2 +from cvwrap import cv2 import time import platform import scipy.sparse as sp diff --git a/serialization.py b/serialization.py index c1df241..b816cc9 100644 --- a/serialization.py +++ b/serialization.py @@ -9,7 +9,7 @@ __all__ = ['load_mesh', 'load_image'] from os.path import split, splitext, join, exists, normpath -import cv2 +from cvwrap import cv2 import numpy as np from dummy import Minimal diff --git a/setup.py b/setup.py index 1d25dda..b6b3be6 100644 --- a/setup.py +++ b/setup.py @@ -6,11 +6,18 @@ from setuptools import setup from distutils.extension import Extension -from Cython.Build import cythonize import numpy import platform import os +try: + from Cython.Build import cythonize + have_cython = True +except: + cythonize = lambda x : x + have_cython = False + + # setuptools DWIM monkey-patch madness # http://mail.python.org/pipermail/distutils-sig/2007-September/thread.html#8204 import sys @@ -53,7 +60,7 @@ def autogen_opengl_sources(): def setup_opendr(ext_modules): ext_modules=cythonize(ext_modules) setup(name='opendr', - version='0.57', + version='0.63', packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], package_dir = {'opendr': '.'}, author = 'Matthew Loper', @@ -61,7 +68,7 @@ def setup_opendr(ext_modules): url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - install_requires=['cython', 'chumpy >= 0.53', 'matplotlib'], + install_requires=['Cython', 'chumpy >= 0.53', 'matplotlib'], description='opendr', ext_modules=ext_modules, license='MIT', @@ -96,10 +103,12 @@ def setup_opendr(ext_modules): def mesa_ext(): libraries = ['OSMesa', 'GL', 'GLU'] extra_args = [] - if platform.system()=='Darwin': + if platform.system()=='Darwin': # deprecated, probably don't need osmesa libs on mac libraries.append('talloc') extra_args.append('-Qunused-arguments') - return Extension("contexts.ctx_mesa", ['contexts/ctx_mesa.pyx'], + else: + extra_args.append('-lstdc++') + return Extension("contexts.ctx_mesa", ['contexts/ctx_mesa.pyx'] if have_cython else ['contexts/ctx_mesa.c'], language="c", library_dirs=['contexts/OSMesa/lib'], depends=['contexts/_constants.py'], @@ -110,7 +119,7 @@ def mesa_ext(): extra_link_args=extra_args) def mac_ext(): - return Extension("contexts.ctx_mac", ['contexts/ctx_mac.pyx', 'contexts/ctx_mac_internal.c'], + return Extension("contexts.ctx_mac", ['contexts/ctx_mac.pyx', 'contexts/ctx_mac_internal.c'] if have_cython else ['contexts/ctx_mac.c', 'contexts/ctx_mac_internal.c'], language="c", depends=['contexts/_constants.py', 'contexts/ctx_mac_internal.h'], include_dirs=['.', numpy.get_include()], @@ -128,7 +137,7 @@ def main(): # Get context extensions ready & build if platform.system() == 'Darwin': - setup_opendr([mesa_ext(), mac_ext()]) + setup_opendr([mac_ext()]) else: setup_opendr([mesa_ext()]) From fd34422f1b4da518ffc8c4d49b3a20047071ff1f Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Thu, 28 Aug 2014 15:55:38 -0400 Subject: [PATCH 26/56] Updated to make pyramids work with greyscale (ie renderer.num_channels==1) --- filters.py | 47 ++++++++++++++++++++++++----------------------- test_renderer.py | 17 ++++++++++++++++- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/filters.py b/filters.py index bc0f1f9..52279e7 100755 --- a/filters.py +++ b/filters.py @@ -6,7 +6,7 @@ See LICENCE.txt for licensing and contact information. """ -__all__ = ['gaussian_pyramid', 'laplacian_pyramid'] +__all__ = ['gaussian_pyramid', 'laplacian_pyramid', 'GaussPyrDownOne'] from cvwrap import cv2 import chumpy as ch @@ -24,15 +24,15 @@ def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list elif normalization is 'SSE': norm2 = lambda x : x / np.sqrt(np.sum(x.r**2.)) elif normalization is 'size': - norm2 = lambda x : x / np.sqrt(x.r.size) + norm2 = lambda x : x / x.r.size else: - raise Exception('Normalization must be None, SSE, or size.') + norm2 = normalization output_objs = [] for level in range(n_levels): - blur_mtx = filter_for(imshape[0], imshape[1], imshape[2], kernel = GaussianKernel2D(3, 1)) + blur_mtx = filter_for(imshape[0], imshape[1], imshape[2] if len(imshape)>2 else 1, kernel = GaussianKernel2D(3, 1)) blurred = MatVecMult(blur_mtx, input_objective).reshape(imshape) output_objs.append(norm2(input_objective - blurred)) @@ -56,9 +56,9 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level elif normalization is 'SSE': norm2 = lambda x : x / np.sqrt(np.sum(x.r**2.)) elif normalization is 'size': - norm2 = lambda x : x / np.sqrt(x.r.size) + norm2 = lambda x : x / x.r.size else: - raise Exception('Normalization must be None, SSE, or size.') + norm2 = normalization cur_imshape = deepcopy(imshape) cur_obj = input_objective @@ -124,7 +124,7 @@ def compute_dr_wrt(self, wrt): def halfsampler_for(shape): h = shape[0] w = shape[1] - d = shape[2] + d = shape[2] if len(shape) > 2 else 1 JS = np.arange(h*w*d).reshape((h,w,d)) JS = JS[::2,::2,:] @@ -133,16 +133,17 @@ def halfsampler_for(shape): IS = np.arange(len(JS)) data = np.ones(len(JS)) - shape = (int(np.ceil(h/2.)), int(np.ceil(w/2.)), int(d)) + if len(shape) > 2: + shape = (int(np.ceil(h/2.)), int(np.ceil(w/2.)), int(d)) + else: + shape = (int(np.ceil(h/2.)), int(np.ceil(w/2.))) return sp.csc_matrix((data, (IS, JS)), shape=(len(IS), h*w*d)), shape def filter_for_nopadding(shape, kernel): - assert(len(shape)==3) - #new_shape = (shape - np.array([kernel.shape[0] - 1, kernel.shape[1] - 1, 0])).astype(np.uint32) - new_shape = (shape - np.array([kernel.shape[0] - 1, kernel.shape[1] - 1, 0])) - new_shape[new_shape<0] = 0.0 - new_shape = new_shape.astype(np.uint32) + new_shape = np.array(shape).copy() + new_shape[0] -= kernel.shape[0] - 1 + new_shape[1] -= kernel.shape[1] - 1 IS = [] JS = [] @@ -169,16 +170,16 @@ def filter_for_nopadding(shape, kernel): IS = np.concatenate(IS) JS = np.concatenate(JS) data = np.concatenate(data) - - d = int(shape[2]) - if d > 1: - IS = [IS*d+k for k in range(d)] - JS = [JS*d+k for k in range(d)] - data = [data for k in range(d)] - IS = np.concatenate(IS) - JS = np.concatenate(JS) - data = np.concatenate(data) - + + if len(shape) > 2: + d = int(shape[2]) + if d > 1: + IS = [IS*d+k for k in range(d)] + JS = [JS*d+k for k in range(d)] + data = [data for k in range(d)] + IS = np.concatenate(IS) + JS = np.concatenate(JS) + data = np.concatenate(data) return sp.csc_matrix((data, (IS, JS))), new_shape diff --git a/test_renderer.py b/test_renderer.py index 426ae42..59818e0 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -81,6 +81,21 @@ def load_basics(self): lightings = {1: lighting_1channel, 3: lighting_3channel} return mesh, lightings, camera, frustum, renderers + def test_pyramids(self): + """ Test that pyramid construction doesn't crash. No quality testing here. """ + mesh, lightings, camera, frustum, renderers = self.load_basics() + from opendr.filters import gaussian_pyramid, laplacian_pyramid, GaussPyrDownOne + + camera.v = mesh.v + for rn in renderers: + lightings[rn.num_channels].v = camera.v + rn.vc = lightings[rn.num_channels] + rn_pyr = gaussian_pyramid(rn, normalization=None, n_levels=2) + rn_lap = laplacian_pyramid(rn, normalization=None, imshape=rn.shape, as_list=False, n_levels=2) + rn_gpr = GaussPyrDownOne(im_shape=rn.shape, want_downsampling=True, px=rn) + for r in [rn_pyr, rn_lap, rn_gpr]: + _ = r.r + #_ = r.dr_wrt(rn.v) def test_distortion(self): mesh, lightings, camera, frustum, renderers = self.load_basics() @@ -115,7 +130,7 @@ def test_distortion(self): [0, 0, 1] ]) - import cv2 + from cvwrap import cv2 im_undistorted = cv2.undistort(im_distorted, cmtx, cr.camera.k.r) d1 = (im_original - im_distorted).ravel() From 64bdd868ab5e004e7405f002bdca7d059b5e0cd4 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Thu, 28 Aug 2014 15:56:01 -0400 Subject: [PATCH 27/56] __init__.py: updated demo('optimization') example --- __init__.py | 50 +++++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/__init__.py b/__init__.py index fa09693..b32eff5 100644 --- a/__init__.py +++ b/__init__.py @@ -235,61 +235,49 @@ def test(): from opendr.simple import * import numpy as np import matplotlib.pyplot as plt -w, h = 320, 240 +w, h = 320, 240 try: m = load_mesh('earth.obj') except: from opendr.util_tests import get_earthmesh - m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) + 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)) -U = ProjectPoints(v=V, f=[300,300.], c=[w/2.,h/2.], k=ch.zeros(5), +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,4]), ch.zeros(3) +translation, rotation = ch.array([0,0,8]), ch.zeros(3) f.v = translation + V.dot(Rodrigues(rotation)) - + observed = f.r -translation[:] = translation.r + np.random.rand(3)*.2 -rotation[:] = rotation.r + np.random.rand(3)*.2 +translation[:] = translation.r + np.random.rand(3) +rotation[:] = rotation.r + np.random.rand(3) *.2 A.components[1:] = 0 # Create the energy -difference = f - observed -E = gaussian_pyramid(difference, n_levels=6, as_list=True)[-3:] -E = ch.concatenate([e.ravel() for e in E]) - -plt.ion() -global cb -global difference -global plt +E_raw = f - observed +E_pyr = gaussian_pyramid(E_raw, n_levels=6, normalization='size') def cb(_): - plt.imshow(np.abs(difference.r)) - plt.title('Absolute difference') - plt.draw() - - -# Minimize the energy -light_parms = A.components -print 'OPTIMIZING TRANSLATION' -ch.minimize({'energy': E}, x0=[translation], callback=lambda _ : cb(difference)) - -print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS (coarse)' -ch.minimize({'energy': E}, x0=[translation, rotation, light_parms], callback=cb) - -print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS (refined)' -E = gaussian_pyramid(difference, n_levels=6, normalization='size') -ch.minimize({'energy': E}, x0=[translation, rotation, light_parms], callback=cb) + import cv2 + global E_raw + cv2.imshow('Absolute difference', np.abs(E_raw.r)) + cv2.waitKey(1) + +print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' +free_variables=[translation, rotation, A.components] +ch.minimize({'pyr': E_pyr}, x0=free_variables, callback=cb) +ch.minimize({'raw': E_raw}, x0=free_variables, callback=cb) """ From d8b15ce9f691a92ae90cba93a90f0f939dbf8714 Mon Sep 17 00:00:00 2001 From: Matthew Loper Date: Thu, 28 Aug 2014 15:57:34 -0400 Subject: [PATCH 28/56] test_renderer.py: fix import --- test_renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_renderer.py b/test_renderer.py index 59818e0..2f51920 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -84,7 +84,7 @@ def load_basics(self): def test_pyramids(self): """ Test that pyramid construction doesn't crash. No quality testing here. """ mesh, lightings, camera, frustum, renderers = self.load_basics() - from opendr.filters import gaussian_pyramid, laplacian_pyramid, GaussPyrDownOne + from filters import gaussian_pyramid, laplacian_pyramid, GaussPyrDownOne camera.v = mesh.v for rn in renderers: From cbf05de290000822b7adc6627405f2f0a5550c6a Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 24 Feb 2015 18:00:39 -0500 Subject: [PATCH 29/56] Add double sided rendering to LambertianPointLight. This pulls in the changes from korper made to the old offscreen_pyrenderer by Paul in 7cd62887. --- lighting.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lighting.py b/lighting.py index d1df3c6..22ec2ed 100755 --- a/lighting.py +++ b/lighting.py @@ -180,12 +180,16 @@ def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_ class LambertianPointLight(Ch): - terms = 'f', 'num_verts', 'light_color' + terms = 'f', 'num_verts', 'light_color', 'double_sided' dterms = 'light_pos', 'v', 'vc', 'vn' def on_changed(self, which): if not hasattr(self, '_lpl'): - self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) + if getattr(self, 'double_sided', False): + self.add_dterm('_lpl', absolute(multiply(a=multiply()))) + self._lpl.a = self._lpl.x + else: + self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) if not hasattr(self, 'ldn'): self.ldn = LightDotNormal(self.v.r.size/3) if not hasattr(self, 'vn'): From 7a89ea4921c5bfc452d26965bbc9b7d104fcca41 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 24 Feb 2015 18:37:19 -0500 Subject: [PATCH 30/56] Fix to prev --- lighting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lighting.py b/lighting.py index 22ec2ed..055f9a9 100755 --- a/lighting.py +++ b/lighting.py @@ -186,6 +186,7 @@ class LambertianPointLight(Ch): def on_changed(self, which): if not hasattr(self, '_lpl'): if getattr(self, 'double_sided', False): + from chumpy.ch import abs as absolute self.add_dterm('_lpl', absolute(multiply(a=multiply()))) self._lpl.a = self._lpl.x else: From 2861d8232d3462c62d944f20dc4675a5a85161ae Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 24 Feb 2015 19:09:11 -0500 Subject: [PATCH 31/56] Leave no pdb unturned --- camera.py | 44 +++++----------- common.py | 2 +- contexts/draw_triangle_shaders_2_1.py | 2 +- contexts/draw_triangle_shaders_3_2.py | 2 +- occlusion_test.py | 2 +- renderer.py | 76 ++++++++++----------------- rogrenderer.py | 2 +- test_depth_renderer.py | 2 +- test_renderer.py | 12 ++--- test_sh.py | 2 +- 10 files changed, 53 insertions(+), 93 deletions(-) diff --git a/camera.py b/camera.py index c6cd4e6..473df6a 100755 --- a/camera.py +++ b/camera.py @@ -161,59 +161,43 @@ class ProjectPoints3D(ProjectPoints): def compute_r(self): result = ProjectPoints.compute_r(self) return np.hstack((result, col(self.z_coords.r))) - + @property def z_coords(self): - - try: - assert(self.v.r.shape[1]==3) - return RigidTransform(v=self.v, rt=self.rt, t=self.t)[:,2] - except: - import pdb; pdb.set_trace() - + assert(self.v.r.shape[1]==3) + return RigidTransform(v=self.v, rt=self.rt, t=self.t)[:,2] + def compute_dr_wrt(self, wrt): result = ProjectPoints.compute_dr_wrt(self, wrt) if result is None: return None - if sp.issparse(result): drz = self.z_coords.dr_wrt(wrt).tocoo() result = result.tocoo() result.row = result.row*3/2 - IS = np.concatenate((result.row, drz.row*3+2)) JS = np.concatenate((result.col, drz.col)) data = np.concatenate((result.data, drz.data)) - result = sp.csc_matrix((data, (IS, JS)), shape=(self.v.r.size, wrt.r.size)) else: - try: - bigger = np.zeros((result.shape[0]/2, 3, result.shape[1])) - bigger[:, :2, :] = result.reshape((-1, 2, result.shape[-1])) - drz = self.z_coords.dr_wrt(wrt) - if drz is not None: - if sp.issparse(drz): - drz = drz.todense() - bigger[:,2,:] = drz.reshape(bigger[:,2,:].shape) - - result = bigger.reshape((-1, bigger.shape[-1])) - except: - import pdb; pdb.set_trace() - - - return result - - + bigger = np.zeros((result.shape[0]/2, 3, result.shape[1])) + bigger[:, :2, :] = result.reshape((-1, 2, result.shape[-1])) + drz = self.z_coords.dr_wrt(wrt) + if drz is not None: + if sp.issparse(drz): + drz = drz.todense() + bigger[:,2,:] = drz.reshape(bigger[:,2,:].shape) + result = bigger.reshape((-1, bigger.shape[-1])) + return result + def main(): - import unittest from test_camera import TestCamera suite = unittest.TestLoader().loadTestsFromTestCase(TestCamera) unittest.TextTestRunner(verbosity=2).run(suite) - if __name__ == '__main__': main() diff --git a/common.py b/common.py index 20bf5d8..f632d2f 100755 --- a/common.py +++ b/common.py @@ -107,7 +107,7 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid plt.subplot(122) plt.imshow(xdiffbnd) plt.title('xdiffbnd') - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() idxs = np.isnan(xdiffnb.ravel()) xdiffnb.ravel()[idxs] = xdiffbnd.ravel()[idxs] diff --git a/contexts/draw_triangle_shaders_2_1.py b/contexts/draw_triangle_shaders_2_1.py index d57957c..8ffd068 100644 --- a/contexts/draw_triangle_shaders_2_1.py +++ b/contexts/draw_triangle_shaders_2_1.py @@ -73,7 +73,7 @@ def main(): im = gl.getImage() cv2.imshow('a', im) - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/contexts/draw_triangle_shaders_3_2.py b/contexts/draw_triangle_shaders_3_2.py index 05e994e..6665d99 100644 --- a/contexts/draw_triangle_shaders_3_2.py +++ b/contexts/draw_triangle_shaders_3_2.py @@ -138,7 +138,7 @@ def main(): im = gl.getImage() cv2.imshow('a', im) print gl.GetError() - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/occlusion_test.py b/occlusion_test.py index 503abd6..180d399 100644 --- a/occlusion_test.py +++ b/occlusion_test.py @@ -137,4 +137,4 @@ def test_occlusion(self): visualize = True suite = unittest.TestLoader().loadTestsFromTestCase(TestOcclusion) unittest.TextTestRunner(verbosity=2).run(suite) - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/renderer.py b/renderer.py index 6129ac1..b3e6bb9 100755 --- a/renderer.py +++ b/renderer.py @@ -393,32 +393,21 @@ def filter_for_triangles(self, which_triangles): @depends_on('f', 'camera', 'vc') def boundarycolor_image(self): - - try: - return self.draw_boundarycolor_image(with_vertex_colors=True) - except: - import pdb; pdb.set_trace() + return self.draw_boundarycolor_image(with_vertex_colors=True) def draw_color_image(self, gl): self._call_on_changed() - try: - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - # use face colors if given - # FIXME: this won't work for 2 channels - draw_colored_verts(gl, self.v.r, self.f, self.vc.r) - - result = np.asarray(deepcopy(gl.getImage()[:,:,:self.num_channels].squeeze()), np.float64) - - if hasattr(self, 'background_image'): - bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,self.num_channels)).squeeze() - fg_px = 1 - bg_px - result = bg_px * self.background_image + fg_px * result - - return result - except: - import pdb; pdb.set_trace() + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + # use face colors if given + # FIXME: this won't work for 2 channels + draw_colored_verts(gl, self.v.r, self.f, self.vc.r) + result = np.asarray(deepcopy(gl.getImage()[:,:,:self.num_channels].squeeze()), np.float64) + if hasattr(self, 'background_image'): + bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,self.num_channels)).squeeze() + fg_px = 1 - bg_px + result = bg_px * self.background_image + fg_px * result + return result @depends_on(dterms+terms) def color_image(self): @@ -443,20 +432,16 @@ def boundary_images(self): self._call_on_changed() return draw_boundary_images(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera) - @depends_on(terms+dterms) - def boundarycolor_image(self): + @depends_on(terms+dterms) + def boundarycolor_image(self): self._call_on_changed() - try: - gl = self.glf - colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - draw_colored_primitives(gl, self.v.r.reshape((-1,3)), self.vpe, colors) - return np.asarray(deepcopy(gl.getImage()), np.float64) - except: - import pdb; pdb.set_trace() - + gl = self.glf + colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + draw_colored_primitives(gl, self.v.r.reshape((-1,3)), self.vpe, colors) + return np.asarray(deepcopy(gl.getImage()), np.float64) + - class TexturedRenderer(ColoredRenderer): terms = 'f', 'frustum', 'vt', 'ft', 'background_image', 'overdraw' dterms = 'vc', 'camera', 'bgcolor', 'texture_image' @@ -569,20 +554,17 @@ def boundaryid_image(self): return result - @depends_on(terms+dterms) - def boundarycolor_image(self): + @depends_on(terms+dterms) + def boundarycolor_image(self): self._call_on_changed() - try: - gl = self.glf - colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - self.texture_mapping_on(gl, with_vertex_colors=False if colors is None else True) - gl.TexCoordPointerf(2,0, self.wireframe_tex_coords.ravel()) - draw_colored_primitives(self.glf, self.v.r.reshape((-1,3)), self.vpe, colors) - self.texture_mapping_off(gl) - return np.asarray(deepcopy(gl.getImage()), np.float64) - except: - import pdb; pdb.set_trace() + gl = self.glf + colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + self.texture_mapping_on(gl, with_vertex_colors=False if colors is None else True) + gl.TexCoordPointerf(2,0, self.wireframe_tex_coords.ravel()) + draw_colored_primitives(self.glf, self.v.r.reshape((-1,3)), self.vpe, colors) + self.texture_mapping_off(gl) + return np.asarray(deepcopy(gl.getImage()), np.float64) def draw_color_image(self, with_vertex_colors=True, with_texture_on=True): self._call_on_changed() diff --git a/rogrenderer.py b/rogrenderer.py index 07f7070..b4d96c8 100644 --- a/rogrenderer.py +++ b/rogrenderer.py @@ -90,4 +90,4 @@ def compute_rog(self, im, is_real=False): r2 -= np.min(r2.ravel()) r2 /= np.max(r2.ravel()) plt.imshow(r2) - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/test_depth_renderer.py b/test_depth_renderer.py index de7fffb..080bbb6 100644 --- a/test_depth_renderer.py +++ b/test_depth_renderer.py @@ -137,4 +137,4 @@ def test_derivatives2(self): #unittest.main() suite = unittest.TestLoader().loadTestsFromTestCase(TestDepthRenderer) unittest.TextTestRunner(verbosity=2).run(suite) - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/test_renderer.py b/test_renderer.py index 04c23f4..67d8f7b 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -425,10 +425,7 @@ def test_color_derivatives(self): # print '-------------------------------------------' #lighting.set(vc=mesh_colors, v=mesh_verts) - try: - lighting.vc = mesh_colors[:,:renderer.num_channels] - except: - import pdb; pdb.set_trace() + lighting.vc = mesh_colors[:,:renderer.num_channels] lighting.v = mesh_verts renderer.set(v=mesh_verts, vc=lighting) @@ -454,10 +451,7 @@ def test_color_derivatives(self): dr_empirical = (np.asarray(rfwd, np.float64) - np.asarray(rbwd, np.float64)).ravel() / eps - try: - dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) - except: - import pdb; pdb.set_trace() + dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) images = OrderedDict() images['shifted colors'] = np.asarray(rfwd, np.float64)-.5 @@ -499,5 +493,5 @@ def plt_imshow(im): suite = unittest.TestLoader().loadTestsFromTestCase(TestRenderer) unittest.TextTestRunner(verbosity=2).run(suite) plt.show() - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() diff --git a/test_sh.py b/test_sh.py index 6b789e1..16dbb37 100755 --- a/test_sh.py +++ b/test_sh.py @@ -153,5 +153,5 @@ def get_sphere_mesh(): suite = unittest.TestLoader().loadTestsFromTestCase(TestSphericalHarmonics) unittest.TextTestRunner(verbosity=2).run(suite) plt.show() - import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() From d80338631392e0b407c2e913fa0c43bbd6a4e551 Mon Sep 17 00:00:00 2001 From: Sonny Date: Tue, 21 Apr 2015 10:23:01 -0400 Subject: [PATCH 32/56] Implement ProjectPoints.compute_r without calling cv2.projectPoints which will compute jacobian --- camera.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/camera.py b/camera.py index 473df6a..a1b7cd9 100755 --- a/camera.py +++ b/camera.py @@ -78,8 +78,29 @@ def is_valid(self): return True, '' def compute_r(self): - return self.r_and_derivatives[0].squeeze() + #return self.r_and_derivatives[0].squeeze() #return self.get_r_and_derivatives(self.v.r, self.rt.r, self.t.r, self.f.r, self.c.r, self.k.r)[0].squeeze() + # method self.r_and_derivatives will compute derivatives as well + #see http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html + v_t = self.v.r + if np.any(self.rt.r != 0.): + v_t = (v_t).dot(cv2.Rodrigues(self.rt.r)[0].T) + if np.any(self.t.r != 0.): + v_t += self.t.r + + x_y = v_t[:,:2] / v_t[:,[2]] + uv = x_y + if np.any(self.k.r != 0.): + k1, k2, p1, p2, k3 = self.k.r + x2_y2 = x_y ** 2. + r2 = x2_y2.sum(axis=1) + r4 = r2 ** 2. + xy = x_y.prod(axis=1) + uv = x_y * (1 + k1 * r2 + k2 * r4 + k3 * r2 * r4)[:,np.newaxis] + uv += 2*np.vstack([p1 * xy, p2 * xy]).T + uv += np.array([p2, p1]) * (r2[:,np.newaxis] + 2 * x2_y2) + uv = self.f.r*uv + self.c.r + return uv def compute_dr_wrt(self, wrt): if wrt not in [self.v, self.rt, self.t, self.f, self.c, self.k]: From 99a126dc76b38f14236d8d423e498f39af6131df Mon Sep 17 00:00:00 2001 From: Sonny Date: Tue, 21 Apr 2015 11:18:54 -0400 Subject: [PATCH 33/56] fix for tests --- camera.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/camera.py b/camera.py index a1b7cd9..a98122f 100755 --- a/camera.py +++ b/camera.py @@ -82,7 +82,7 @@ def compute_r(self): #return self.get_r_and_derivatives(self.v.r, self.rt.r, self.t.r, self.f.r, self.c.r, self.k.r)[0].squeeze() # method self.r_and_derivatives will compute derivatives as well #see http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html - v_t = self.v.r + v_t = self.v.r.reshape((-1,3)).copy() if np.any(self.rt.r != 0.): v_t = (v_t).dot(cv2.Rodrigues(self.rt.r)[0].T) if np.any(self.t.r != 0.): @@ -91,15 +91,25 @@ def compute_r(self): x_y = v_t[:,:2] / v_t[:,[2]] uv = x_y if np.any(self.k.r != 0.): - k1, k2, p1, p2, k3 = self.k.r + k = self.k.r + # According to this link: http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html + # k can have three lengths: (k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]]) + if len(k) == 4: + k1, k2, p1, p2 = k + elif len(k) == 5: + k1, k2, p1, p2, k3 = k + elif len(k) == 8: + k1, k2, p1, p2, k3, k4, k5, k6 = k + else: + raise AttributeError('k has wrong length, got %d, expect 4, 5 or 8' % len(k)) x2_y2 = x_y ** 2. r2 = x2_y2.sum(axis=1) r4 = r2 ** 2. xy = x_y.prod(axis=1) uv = x_y * (1 + k1 * r2 + k2 * r4 + k3 * r2 * r4)[:,np.newaxis] - uv += 2*np.vstack([p1 * xy, p2 * xy]).T + uv += 2 * np.vstack([p1 * xy, p2 * xy]).T uv += np.array([p2, p1]) * (r2[:,np.newaxis] + 2 * x2_y2) - uv = self.f.r*uv + self.c.r + uv = self.f.r * uv + self.c.r return uv def compute_dr_wrt(self, wrt): From 53c6de5229848c99da4d3adb23b286b91ca5af30 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 21 Apr 2015 11:58:40 -0400 Subject: [PATCH 34/56] Failing test that changes to ProjectPoints didn't change anything --- test_camera.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test_camera.py b/test_camera.py index 63178f9..2ca5243 100755 --- a/test_camera.py +++ b/test_camera.py @@ -31,8 +31,20 @@ def get_cam_params(self): cam_params = {'v': ch.Ch(v_raw), 'rt': rt, 't': t, 'f': f, 'c': c, 'k': k} return cam_params + def test_project_points_without_derivatives(self): + from util_tests import get_earthmesh + cam_params = self.get_cam_params() + mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) + + pp = ProjectPoints(f=cam_params['f'], rt=cam_params['rt'], t=cam_params['t'], k=cam_params['k'], c=cam_params['c']) + pp.v = mesh.v + + np.testing.assert_array_equal(pp.r, pp.r_and_derivatives[0].squeeze()) + def test_project_points(self): self.project_points(ProjectPoints) + + def test_project_points_3d(self): self.project_points(ProjectPoints3D) def project_points(self, cls): From b64493ea832aeee13202c7165860c5273f44dff0 Mon Sep 17 00:00:00 2001 From: Chenyang Liu Date: Mon, 27 Apr 2015 12:31:35 -0400 Subject: [PATCH 35/56] Return squeezed R for backward compatibility --- camera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camera.py b/camera.py index a98122f..0bcc7dd 100755 --- a/camera.py +++ b/camera.py @@ -110,7 +110,7 @@ def compute_r(self): uv += 2 * np.vstack([p1 * xy, p2 * xy]).T uv += np.array([p2, p1]) * (r2[:,np.newaxis] + 2 * x2_y2) uv = self.f.r * uv + self.c.r - return uv + return uv.squeeze() def compute_dr_wrt(self, wrt): if wrt not in [self.v, self.rt, self.t, self.f, self.c, self.k]: From 7e0961ea2a9ec2390ab5c2eca7b002e5bd9d98a2 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Mon, 18 May 2015 16:28:15 -0400 Subject: [PATCH 36/56] Loosened tests slightly for buildbot --- test_camera.py | 2 +- test_renderer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test_camera.py b/test_camera.py index 2ca5243..ab7952a 100755 --- a/test_camera.py +++ b/test_camera.py @@ -39,7 +39,7 @@ def test_project_points_without_derivatives(self): pp = ProjectPoints(f=cam_params['f'], rt=cam_params['rt'], t=cam_params['t'], k=cam_params['k'], c=cam_params['c']) pp.v = mesh.v - np.testing.assert_array_equal(pp.r, pp.r_and_derivatives[0].squeeze()) + np.testing.assert_array_almost_equal(pp.r, pp.r_and_derivatives[0].squeeze()) def test_project_points(self): self.project_points(ProjectPoints) diff --git a/test_renderer.py b/test_renderer.py index 67d8f7b..8aad505 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -185,7 +185,7 @@ def test_cam_derivatives(self): mesh, lightings, camera, frustum, renderers = self.load_basics() camparms = { - 'c': {'mednz' : 2.2e-2, 'meannz': 4.2e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, + 'c': {'mednz' : 2.2e-2, 'meannz': 4.3e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, #'f': {'mednz' : 2.5e-2, 'meannz': 6e-2, 'desc': 'focal diff', 'eps0': 100., 'eps1': .1}, 't': {'mednz' : 1.2e-1, 'meannz': 3.0e-1, 'desc': 'trans diff', 'eps0': .25, 'eps1': .1}, 'rt': {'mednz' : 8e-2, 'meannz': 1.8e-1, 'desc': 'rot diff', 'eps0': 0.02, 'eps1': .5}, From 8c61bdd68f81c6a98ddf6af03af93819994a264d Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Mon, 6 Jul 2015 11:01:58 -0400 Subject: [PATCH 37/56] Remove monkey patch to setuptools that appears to no longer be necessary --- setup.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/setup.py b/setup.py index eb549e7..c01f6d7 100644 --- a/setup.py +++ b/setup.py @@ -18,14 +18,6 @@ cythonize = lambda x : x have_cython = False - -# setuptools DWIM monkey-patch madness -# http://mail.python.org/pipermail/distutils-sig/2007-September/thread.html#8204 -import sys -if 'setuptools.extension' in sys.modules: - m = sys.modules['setuptools.extension'] - m.Extension.__dict__ = m._Extension.__dict__ - context_dir = os.path.join(os.path.dirname(__file__), 'contexts') osmesa_mirrors = [ From c521273967a8b063a5e7a633ca463a2e10821586 Mon Sep 17 00:00:00 2001 From: EERac Date: Fri, 24 Jul 2015 16:24:29 -0400 Subject: [PATCH 38/56] removed superflous copy operation in camera.unproject_points that was in practice being applied to a ch.array (created in camera.unproject_depth_image for some unknown reason). 25x speedup. --- camera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camera.py b/camera.py index 0bcc7dd..0b5bbb9 100755 --- a/camera.py +++ b/camera.py @@ -139,7 +139,7 @@ def unproject_points(self, uvd, camera_space=False): cam = ProjectPoints3D(**{k: getattr(self, k) for k in self.dterms if hasattr(self, k)}) try: - xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2)).copy()), np.asarray(cam.camera_mtx), cam.k.r) + xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2))), np.asarray(cam.camera_mtx), cam.k.r) xyz_camera_space = np.hstack((xy_undistorted_camspace.squeeze(), col(uvd[:,2]))) xyz_camera_space[:,:2] *= col(xyz_camera_space[:,2]) # scale x,y by z if camera_space: From ee00ad192aadf3c1fb683d95606e33dc9935173a Mon Sep 17 00:00:00 2001 From: Martin Kristiansen Date: Thu, 17 Mar 2016 14:48:57 -0400 Subject: [PATCH 39/56] Fix bad zip downloads during install PR #1 * Catches BadZipFile and retries download once * Now also closes urllib2 connection when done --- setup.py | 53 +++++++++++++++++++++++++++++++++++------------------ utils.py | 1 + 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/setup.py b/setup.py index 07ecc2b..dc43a7a 100644 --- a/setup.py +++ b/setup.py @@ -24,33 +24,50 @@ 'https://s3.amazonaws.com/bodylabs-assets/public/osmesa/', 'http://files.is.tue.mpg.de/mloper/opendr/osmesa/', ] - -def download_osmesa(): - import os, re, zipfile - from utils import wget - mesa_dir = os.path.join(context_dir,'OSMesa') +# Filenames on the above mirrors follow this convention: +sysinfo = platform.uname() +osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2]) + +def download_osmesa(retries_on_bad_zip=1): + from zipfile import BadZipfile + def unzip(fname, dest_dir): + import zipfile, re + with zipfile.ZipFile(fname, 'r') as z: + for f in filter(lambda x: re.search('[ah]$', x), z.namelist()): + z.extract(f, path=dest_dir) + + def download_zip(dest_fname): + from utils import wget + for base_url in osmesa_mirrors: + print "Downloading %s" % (base_url + osmesa_fname, ) + try: + wget(base_url + osmesa_fname, dest_fname=dest_fname) + break + except Exception: + print "File not found, trying mirrors" + + mesa_dir = os.path.join(context_dir, 'OSMesa') if not os.path.exists(mesa_dir): - sysinfo = platform.uname() - osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2]) zip_fname = os.path.join(context_dir, osmesa_fname) if not os.path.exists(zip_fname): - for base_url in osmesa_mirrors: - print "Downloading %s" % (base_url + osmesa_fname, ) - try: - wget(base_url + osmesa_fname, dest_fname=zip_fname) - break - except Exception: - print "File not found, trying mirrors" + download_zip(zip_fname) assert(os.path.exists(zip_fname)) - with zipfile.ZipFile(zip_fname, 'r') as z: - for f in filter(lambda x: re.search('[ah]$', x), z.namelist()): - z.extract(f, path=context_dir) + try: + unzip(zip_fname, context_dir) + except BadZipfile: + if retries_on_bad_zip > 0: + print "Bad zip file; retrying download." + os.remove(zip_fname) + download_osmesa(retries_on_bad_zip=retries_on_bad_zip - 1) + else: + print "Bad zip file; not retrying download again." + raise assert(os.path.exists(mesa_dir)) def autogen_opengl_sources(): import os - sources = [ os.path.join(context_dir, x) for x in ['_constants.py', '_functions.pyx'] ] + sources = [ os.path.join(context_dir, x) for x in ['_constants.py', '_functions.pyx']] if not all([ os.path.exists(x) for x in sources ]): print "Autogenerating opengl sources" from contexts import autogen diff --git a/utils.py b/utils.py index 759cd02..d7c9a8d 100644 --- a/utils.py +++ b/utils.py @@ -31,5 +31,6 @@ def wget(url, dest_fname=None): if contents == "": break f.write(contents) + source.close() except: raise Exception('Unable to get url: %s' % (url,)) From c39ccf97c354577666ed66f8535f0a0937d628d1 Mon Sep 17 00:00:00 2001 From: Martin Kristiansen Date: Fri, 18 Mar 2016 13:25:37 -0400 Subject: [PATCH 40/56] Fix of unit test bug PR #2 --- test_renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_renderer.py b/test_renderer.py index 8aad505..dea9eaa 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -34,7 +34,7 @@ def getcam(): w = 256 h = 192 - f = np.array([200,200]) + f = np.array([200.,200.]) rt = np.zeros(3) t = np.zeros(3) k = np.zeros(5) From 1a373332599c9516deef83647d135648fe9bbc11 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Mon, 30 May 2016 09:37:44 -0400 Subject: [PATCH 41/56] Test in CircleCI (#4) --- circle.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..801a60e --- /dev/null +++ b/circle.yml @@ -0,0 +1,21 @@ +general: + branches: + ignore: + - /zz.*/ # Don't run tests on deprecated branches. + +machine: + environment: + PYTHONPATH: /usr/local/lib/python2.7/dist-packages + +dependencies: + pre: + - sudo apt-get update + # Is gfortran needed? This was copied from `.travis.yml` which included it. + - sudo apt-get install -qq python-dev gfortran pkg-config liblapack-dev + - pip install cython + - 'pip install git+ssh://github.com/bodylabs/chumpy.git@master#egg=chumpy' + - make all + +test: + override: + - make test From 479a143cf694ecc226df905b1c21be656f85faa4 Mon Sep 17 00:00:00 2001 From: Sonny Hu Date: Tue, 31 May 2016 13:45:08 -0400 Subject: [PATCH 42/56] Fix dependencies in setup.py and keep version consistent and RELEASE 0.74.0 (#5) * Fix setup.py * Correct version * Address code review * Use parse_requirements from pip * Fix setup --- circle.yml | 2 -- requirements.txt | 6 ++++-- setup.py | 12 ++++++++---- version.py | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/circle.yml b/circle.yml index 801a60e..ca03bc2 100644 --- a/circle.yml +++ b/circle.yml @@ -12,8 +12,6 @@ dependencies: - sudo apt-get update # Is gfortran needed? This was copied from `.travis.yml` which included it. - sudo apt-get install -qq python-dev gfortran pkg-config liblapack-dev - - pip install cython - - 'pip install git+ssh://github.com/bodylabs/chumpy.git@master#egg=chumpy' - make all test: diff --git a/requirements.txt b/requirements.txt index 4402122..a5e5ac6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ - --e . +cython==0.24 +numpy==1.10.1 +matplotlib==1.5.0 +git+ssh://git@github.com/bodylabs/chumpy.git@0.65.5#egg=chumpy diff --git a/setup.py b/setup.py index dc43a7a..ec6a4bd 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ import platform import os from version import version +from pip.req import parse_requirements try: from Cython.Build import cythonize @@ -28,6 +29,9 @@ sysinfo = platform.uname() osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2]) +install_requires = parse_requirements('requirements.txt', session=False) +install_requires = [str(ir.req) for ir in install_requires] + def download_osmesa(retries_on_bad_zip=1): from zipfile import BadZipfile def unzip(fname, dest_dir): @@ -91,7 +95,7 @@ def setup_opendr(ext_modules): url = 'http://github.com/mattloper/opendr', ext_package='opendr', package_data={'opendr': ['test_dr/nasa*']}, - install_requires=['Cython', 'chumpy >= 0.58', 'matplotlib'], + install_requires=install_requires, description='opendr', ext_modules=ext_modules, license='MIT', @@ -106,7 +110,7 @@ def setup_opendr(ext_modules): # Indicate who your project is intended for 'Intended Audience :: Science/Research', - 'Topic :: Multimedia :: Graphics :: 3D Rendering', + 'Topic :: Multimedia :: Graphics :: 3D Rendering', # Pick your license as you wish (should match "license" above) 'License :: OSI Approved :: MIT License', @@ -115,11 +119,11 @@ def setup_opendr(ext_modules): # that you indicate whether you support Python 2, Python 3 or both. 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', - + 'Operating System :: MacOS :: MacOS X', 'Operating System :: POSIX :: Linux' ], - + ) diff --git a/version.py b/version.py index b4e0bc7..61c470a 100644 --- a/version.py +++ b/version.py @@ -1,3 +1,3 @@ -version = '0.74' +version = '0.75.0' short_version = version full_version = version From ca23ab6941fb59c392dbfae96354fd3f50842cba Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 2 Jun 2016 09:08:39 -0400 Subject: [PATCH 43/56] Don't build until after dependencies are installed (#6) --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index ca03bc2..50ecaf8 100644 --- a/circle.yml +++ b/circle.yml @@ -12,6 +12,7 @@ dependencies: - sudo apt-get update # Is gfortran needed? This was copied from `.travis.yml` which included it. - sudo apt-get install -qq python-dev gfortran pkg-config liblapack-dev + post: - make all test: From 96675e6385b3f1174699a6d56baa427643cd0f3f Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 1 Aug 2016 09:43:02 -0400 Subject: [PATCH 44/56] Update chumpy (#7) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a5e5ac6..4d9d414 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ cython==0.24 numpy==1.10.1 matplotlib==1.5.0 -git+ssh://git@github.com/bodylabs/chumpy.git@0.65.5#egg=chumpy +git+ssh://git@github.com/bodylabs/chumpy.git@0.65.7#egg=chumpy From 9fbe867b43a2f39eaf2406621c840444e876340f Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 11 Apr 2017 16:26:29 -0400 Subject: [PATCH 45/56] relax requirement versions --- requirements.txt | 6 +++--- version.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4d9d414..de0b7af 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -cython==0.24 -numpy==1.10.1 -matplotlib==1.5.0 +cython>=0.24 +numpy>=1.10.1 +matplotlib>=1.5.0 git+ssh://git@github.com/bodylabs/chumpy.git@0.65.7#egg=chumpy diff --git a/version.py b/version.py index 61c470a..b5d8af7 100644 --- a/version.py +++ b/version.py @@ -1,3 +1,3 @@ -version = '0.75.0' +version = '0.75.1' short_version = version full_version = version From 07854463a46bfae10da5f86f0458ac8622dba397 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 11 Apr 2017 16:31:31 -0400 Subject: [PATCH 46/56] update to newest chumpy --- requirements.txt | 2 +- version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index de0b7af..48e2a95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ cython>=0.24 numpy>=1.10.1 matplotlib>=1.5.0 -git+ssh://git@github.com/bodylabs/chumpy.git@0.65.7#egg=chumpy +git+ssh://git@github.com/bodylabs/chumpy.git@0.67.1#egg=chumpy diff --git a/version.py b/version.py index b5d8af7..ff55730 100644 --- a/version.py +++ b/version.py @@ -1,3 +1,3 @@ -version = '0.75.1' +version = '0.75.2' short_version = version full_version = version From 4414aa5d370aca3e76211bb04f6f269b5243d3cf Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 11 Apr 2017 16:39:29 -0400 Subject: [PATCH 47/56] use more recent scipy in chumpy --- requirements.txt | 2 +- version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 48e2a95..b961ce1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ cython>=0.24 numpy>=1.10.1 matplotlib>=1.5.0 -git+ssh://git@github.com/bodylabs/chumpy.git@0.67.1#egg=chumpy +git+ssh://git@github.com/bodylabs/chumpy.git@0.67.2#egg=chumpy diff --git a/version.py b/version.py index ff55730..e16732c 100644 --- a/version.py +++ b/version.py @@ -1,3 +1,3 @@ -version = '0.75.2' +version = '0.75.3' short_version = version full_version = version From f5bf6a7055971d65bea06f34c33b5b90c3b35c14 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Tue, 18 Apr 2017 10:35:57 -0400 Subject: [PATCH 48/56] Fix tests in circle (#9) * Preinstall numpy and scipy as they are needed to compile other stuff * scipy.stats.nanmean has been deprecated since 0.15 * Fix some float-as-index bugs --- circle.yml | 1 + common.py | 4 ++-- filters.py | 15 ++++++++------- renderer.py | 4 ++-- test_renderer.py | 5 +++-- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/circle.yml b/circle.yml index 50ecaf8..001a43a 100644 --- a/circle.yml +++ b/circle.yml @@ -12,6 +12,7 @@ dependencies: - sudo apt-get update # Is gfortran needed? This was copied from `.travis.yml` which included it. - sudo apt-get install -qq python-dev gfortran pkg-config liblapack-dev + - pip install numpy scipy post: - make all diff --git a/common.py b/common.py index f632d2f..914aa6c 100755 --- a/common.py +++ b/common.py @@ -10,7 +10,6 @@ from copy import deepcopy import scipy.sparse as sp from cvwrap import cv2 -import scipy.stats from chumpy.utils import row, col from contexts._constants import * @@ -18,7 +17,8 @@ def nanmean(a, axis): # don't call nan_to_num in here, unless you check that # occlusion_test.py still works after you do it! - result = scipy.stats.nanmean(a, axis=axis) + + result = np.nanmean(a, axis=axis) return result def nangradients(arr): diff --git a/filters.py b/filters.py index bba0b92..586eb56 100755 --- a/filters.py +++ b/filters.py @@ -28,6 +28,7 @@ def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list else: norm2 = normalization + imshape = [int(x) for x in imshape] output_objs = [] for level in range(n_levels): @@ -146,9 +147,9 @@ def compute_dr_wrt(self, wrt): GaussPyrDownOne = GaussPyrDownOneOld def halfsampler_for(shape): - h = shape[0] - w = shape[1] - d = shape[2] if len(shape) > 2 else 1 + h = int(shape[0]) + w = int(shape[1]) + d = int(shape[2]) if len(shape) > 2 else 1 JS = np.arange(h*w*d).reshape((h,w,d)) JS = JS[::2,::2,:] @@ -175,8 +176,8 @@ def filter_for_nopadding(shape, kernel): new_h = int(new_shape[0]) new_w = int(new_shape[1]) - old_h = shape[0] - old_w = shape[1] + old_h = int(shape[0]) + old_w = int(shape[1]) xs = np.tile(np.arange(old_w), (old_h, 1)) ys = np.tile(np.arange(old_h), (old_w, 1)).T.copy() @@ -217,8 +218,8 @@ def filter_for(h, w, d, kernel): kym = (kernel.shape[0]+1) / 2 - xs = np.tile(np.arange(w), (h, 1)) - ys = np.tile(np.arange(h), (w, 1)).T.copy() + xs = np.tile(np.arange(w), (int(h), 1)) + ys = np.tile(np.arange(h), (int(w), 1)).T.copy() IS = [] JS = [] diff --git a/renderer.py b/renderer.py index b3e6bb9..18450fb 100755 --- a/renderer.py +++ b/renderer.py @@ -349,8 +349,8 @@ def compute_dr_wrt(self, wrt): def on_changed(self, which): if 'frustum' in which: - w = self.frustum['width'] - h = self.frustum['height'] + w = int(self.frustum['width']) + h = int(self.frustum['height']) self.glf = OsContext(w, h, typ=GL_FLOAT) self.glf.Viewport(0, 0, w, h) self.glb = OsContext(w, h, typ=GL_UNSIGNED_BYTE) diff --git a/test_renderer.py b/test_renderer.py index dea9eaa..2826dcb 100755 --- a/test_renderer.py +++ b/test_renderer.py @@ -93,8 +93,9 @@ def test_pyramids(self): rn_pyr = gaussian_pyramid(rn, normalization=None, n_levels=2) rn_lap = laplacian_pyramid(rn, normalization=None, imshape=rn.shape, as_list=False, n_levels=2) rn_gpr = GaussPyrDownOne(im_shape=rn.shape, want_downsampling=True, px=rn) - for r in [rn_pyr, rn_lap, rn_gpr]: - _ = r.r + _ = rn_pyr.r + _ = rn_lap.r + _ = rn_gpr.r for r in [rn_pyr, rn_gpr]: for ii in range(3): rn.v[:,:] = rn.v[:,:].r + 1e-10 From f2f11dcbb1dc60ffa4d06a0011998d70f4fa2f02 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Wed, 26 Apr 2017 11:48:05 -0400 Subject: [PATCH 49/56] use pypi chumpy --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b961ce1..3b0206d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ cython>=0.24 numpy>=1.10.1 matplotlib>=1.5.0 -git+ssh://git@github.com/bodylabs/chumpy.git@0.67.2#egg=chumpy +chumpy>=0.67.4 From 8eea8ab4ad1fb6f216b424a4629daae75e810679 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Wed, 10 May 2017 14:05:43 -0400 Subject: [PATCH 50/56] Make pip installable --- .gitignore | 18 +++-- LICENSE.txt => LICENSE | 0 MANIFEST.in | 2 +- README.md | 19 ++++- README.txt | 16 ----- Rakefile | 70 +++++++++++++++++++ circle.yml | 9 +-- __init__.py => opendr/__init__.py | 0 camera.py => opendr/camera.py | 0 common.py => opendr/common.py | 0 {contexts => opendr/contexts}/Makefile | 0 {contexts => opendr/contexts}/__init__.py | 0 {contexts => opendr/contexts}/autogen.py | 0 {contexts => opendr/contexts}/ctx_base.pyx | 0 {contexts => opendr/contexts}/ctx_mac.pyx | 0 .../contexts}/ctx_mac_internal.c | 0 .../contexts}/ctx_mac_internal.h | 0 {contexts => opendr/contexts}/ctx_mesa.pyx | 0 .../contexts}/draw_triangle_shaders_2_1.py | 0 .../contexts}/draw_triangle_shaders_3_2.py | 0 {contexts => opendr/contexts}/fix_warnings.py | 0 {contexts => opendr/contexts}/gl_includes.h | 0 cvwrap.py => opendr/cvwrap.py | 0 dummy.py => opendr/dummy.py | 0 everything.py => opendr/everything.py | 0 filters.py => opendr/filters.py | 0 geometry.py => opendr/geometry.py | 0 lighting.py => opendr/lighting.py | 0 renderer.py => opendr/renderer.py | 0 rogrenderer.py => opendr/rogrenderer.py | 0 serialization.py => opendr/serialization.py | 0 simple.py => opendr/simple.py | 0 slider_demo.py => opendr/slider_demo.py | 0 test_camera.py => opendr/test_camera.py | 0 .../test_depth_renderer.py | 0 test_geometry.py => opendr/test_geometry.py | 0 test_renderer.py => opendr/test_renderer.py | 0 test_sh.py => opendr/test_sh.py | 0 topology.py => opendr/topology.py | 0 util_tests.py => opendr/util_tests.py | 0 utils.py => opendr/utils.py | 0 version.py => opendr/version.py | 2 +- requirements_dev.txt | 4 ++ setup.py | 36 ++++++---- test_dr/Makefile | 5 -- test_dr/__init__.py | 0 46 files changed, 129 insertions(+), 52 deletions(-) rename LICENSE.txt => LICENSE (100%) delete mode 100644 README.txt create mode 100644 Rakefile rename __init__.py => opendr/__init__.py (100%) rename camera.py => opendr/camera.py (100%) rename common.py => opendr/common.py (100%) rename {contexts => opendr/contexts}/Makefile (100%) rename {contexts => opendr/contexts}/__init__.py (100%) rename {contexts => opendr/contexts}/autogen.py (100%) rename {contexts => opendr/contexts}/ctx_base.pyx (100%) rename {contexts => opendr/contexts}/ctx_mac.pyx (100%) rename {contexts => opendr/contexts}/ctx_mac_internal.c (100%) rename {contexts => opendr/contexts}/ctx_mac_internal.h (100%) rename {contexts => opendr/contexts}/ctx_mesa.pyx (100%) rename {contexts => opendr/contexts}/draw_triangle_shaders_2_1.py (100%) rename {contexts => opendr/contexts}/draw_triangle_shaders_3_2.py (100%) rename {contexts => opendr/contexts}/fix_warnings.py (100%) rename {contexts => opendr/contexts}/gl_includes.h (100%) rename cvwrap.py => opendr/cvwrap.py (100%) rename dummy.py => opendr/dummy.py (100%) rename everything.py => opendr/everything.py (100%) rename filters.py => opendr/filters.py (100%) rename geometry.py => opendr/geometry.py (100%) rename lighting.py => opendr/lighting.py (100%) rename renderer.py => opendr/renderer.py (100%) rename rogrenderer.py => opendr/rogrenderer.py (100%) rename serialization.py => opendr/serialization.py (100%) rename simple.py => opendr/simple.py (100%) rename slider_demo.py => opendr/slider_demo.py (100%) rename test_camera.py => opendr/test_camera.py (100%) rename test_depth_renderer.py => opendr/test_depth_renderer.py (100%) rename test_geometry.py => opendr/test_geometry.py (100%) rename test_renderer.py => opendr/test_renderer.py (100%) rename test_sh.py => opendr/test_sh.py (100%) rename topology.py => opendr/topology.py (100%) rename util_tests.py => opendr/util_tests.py (100%) rename utils.py => opendr/utils.py (100%) rename version.py => opendr/version.py (73%) create mode 100644 requirements_dev.txt delete mode 100644 test_dr/Makefile delete mode 100644 test_dr/__init__.py diff --git a/.gitignore b/.gitignore index 01d3041..25824fe 100644 --- a/.gitignore +++ b/.gitignore @@ -52,10 +52,14 @@ coverage.xml # Sphinx documentation docs/_build/ -contexts/OSMesa.Darwin.x86_64.zip -contexts/OSMesa/ -contexts/_constants.py -contexts/_functions.pyx -contexts/ctx_mac.c -contexts/ctx_mesa.c -venv \ No newline at end of file +opendr/contexts/OSMesa.Darwin.x86_64.zip +opendr/contexts/OSMesa/ +opendr/contexts/_constants.py +opendr/contexts/_functions.pyx +opendr/contexts/ctx_mac.c +opendr/contexts/ctx_mesa.c +venv +/bodylabs-python-style/ + +.DS_Store + diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/MANIFEST.in b/MANIFEST.in index b6639cd..d4ba1eb 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ global-include . *.py *.c *.h Makefile nasa* *.pyx -prune contexts/OSMesa +prune opendr/contexts/OSMesa global-exclude . rogrenderer* diff --git a/README.md b/README.md index d0763ed..7ece74f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ -opendr -====== -Testing. \ No newline at end of file +The OpenDR (or Open Differentiable Renderer) can be used for rendering and optimisation to image evidence. + +- Rendering is achieved by constructing and initialising one of the renderers available in OpenDR. +- Optimization is achieved by minimising an objective that includes a renderer. + +OpenDR is useful even without optimisation: if you just wish to animate meshes over time without performing optimisation, OpenDR may still be a good choice for rendering those meshes to images offscreen, for later compilation into a movie. + +OpenDR is also designed to be concise: it should not take many lines of code to construct a scene. Although it will not replace dedicated commercial platforms (such as Maya) for some tasks, it is flexible enough for many tasks, and in some cases goes beyond what Maya can offer. + +OpenDR comes with its own demos, which can be seen by typing the following:: + +>> import opendr +>> opendr.demo() # prints out a list of possible demos + +Licensing is specified in the attached LICENSE.txt. + diff --git a/README.txt b/README.txt deleted file mode 100644 index 7ece74f..0000000 --- a/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -The OpenDR (or Open Differentiable Renderer) can be used for rendering and optimisation to image evidence. - -- Rendering is achieved by constructing and initialising one of the renderers available in OpenDR. -- Optimization is achieved by minimising an objective that includes a renderer. - -OpenDR is useful even without optimisation: if you just wish to animate meshes over time without performing optimisation, OpenDR may still be a good choice for rendering those meshes to images offscreen, for later compilation into a movie. - -OpenDR is also designed to be concise: it should not take many lines of code to construct a scene. Although it will not replace dedicated commercial platforms (such as Maya) for some tasks, it is flexible enough for many tasks, and in some cases goes beyond what Maya can offer. - -OpenDR comes with its own demos, which can be seen by typing the following:: - ->> import opendr ->> opendr.demo() # prints out a list of possible demos - -Licensing is specified in the attached LICENSE.txt. - diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..45d6038 --- /dev/null +++ b/Rakefile @@ -0,0 +1,70 @@ +$style_config_version = '2.1.0' + +desc "Install style config" +task :install_style_config do + FileUtils.rm_rf "bodylabs-python-style" if Dir.exists? "bodylabs-python-style" + raise unless system "git clone https://github.com/bodylabs/bodylabs-python-style.git" + Dir.chdir 'bodylabs-python-style' do + raise unless system "git checkout tags/#{$style_config_version}" + end +end + +task :require_style_config do + Rake::Task[:install_style_config].invoke unless File.executable? 'bodylabs-python-style/bin/pylint_test' +end + +$mac_os = `uname -s`.strip == 'Darwin' + +desc "Install dependencies for distribution" +task :install_dist do + if $mac_os + raise unless system "brew update" + raise unless system "brew install pandoc" + raise unless system "pip install pypandoc" + else + puts + puts "You must install:" + puts + puts " - pandoc" + puts " - pypandoc" + puts + raise + end +end + +def command_is_in_path?(command) + system("which #{ command} > /dev/null 2>&1") +end + +task :test do + raise unless system "nose2" +end + +task :lint => :require_style_config do + raise unless system "bodylabs-python-style/bin/pylint_test opendr --min_rating 10.0" +end + +desc "Remove .pyc files" +task :clean do + system "find . -name '*.pyc' -delete" +end + +task :sdist do + unless command_is_in_path? 'pandoc' + puts + puts "Please install pandoc." + puts + raise + end + raise unless system "python setup.py sdist" +end + +task :upload do + unless command_is_in_path?('pandoc') + puts + puts "Please install pandoc." + puts + raise + end + raise unless system "python setup.py sdist upload" +end diff --git a/circle.yml b/circle.yml index 001a43a..9c96e5f 100644 --- a/circle.yml +++ b/circle.yml @@ -12,10 +12,11 @@ dependencies: - sudo apt-get update # Is gfortran needed? This was copied from `.travis.yml` which included it. - sudo apt-get install -qq python-dev gfortran pkg-config liblapack-dev - - pip install numpy scipy - post: - - make all + - pip install numpy scipy cython + - pip install -r requirements_dev.txt + - pip install -e . test: override: - - make test + - rake test + - rake lint diff --git a/__init__.py b/opendr/__init__.py similarity index 100% rename from __init__.py rename to opendr/__init__.py diff --git a/camera.py b/opendr/camera.py similarity index 100% rename from camera.py rename to opendr/camera.py diff --git a/common.py b/opendr/common.py similarity index 100% rename from common.py rename to opendr/common.py diff --git a/contexts/Makefile b/opendr/contexts/Makefile similarity index 100% rename from contexts/Makefile rename to opendr/contexts/Makefile diff --git a/contexts/__init__.py b/opendr/contexts/__init__.py similarity index 100% rename from contexts/__init__.py rename to opendr/contexts/__init__.py diff --git a/contexts/autogen.py b/opendr/contexts/autogen.py similarity index 100% rename from contexts/autogen.py rename to opendr/contexts/autogen.py diff --git a/contexts/ctx_base.pyx b/opendr/contexts/ctx_base.pyx similarity index 100% rename from contexts/ctx_base.pyx rename to opendr/contexts/ctx_base.pyx diff --git a/contexts/ctx_mac.pyx b/opendr/contexts/ctx_mac.pyx similarity index 100% rename from contexts/ctx_mac.pyx rename to opendr/contexts/ctx_mac.pyx diff --git a/contexts/ctx_mac_internal.c b/opendr/contexts/ctx_mac_internal.c similarity index 100% rename from contexts/ctx_mac_internal.c rename to opendr/contexts/ctx_mac_internal.c diff --git a/contexts/ctx_mac_internal.h b/opendr/contexts/ctx_mac_internal.h similarity index 100% rename from contexts/ctx_mac_internal.h rename to opendr/contexts/ctx_mac_internal.h diff --git a/contexts/ctx_mesa.pyx b/opendr/contexts/ctx_mesa.pyx similarity index 100% rename from contexts/ctx_mesa.pyx rename to opendr/contexts/ctx_mesa.pyx diff --git a/contexts/draw_triangle_shaders_2_1.py b/opendr/contexts/draw_triangle_shaders_2_1.py similarity index 100% rename from contexts/draw_triangle_shaders_2_1.py rename to opendr/contexts/draw_triangle_shaders_2_1.py diff --git a/contexts/draw_triangle_shaders_3_2.py b/opendr/contexts/draw_triangle_shaders_3_2.py similarity index 100% rename from contexts/draw_triangle_shaders_3_2.py rename to opendr/contexts/draw_triangle_shaders_3_2.py diff --git a/contexts/fix_warnings.py b/opendr/contexts/fix_warnings.py similarity index 100% rename from contexts/fix_warnings.py rename to opendr/contexts/fix_warnings.py diff --git a/contexts/gl_includes.h b/opendr/contexts/gl_includes.h similarity index 100% rename from contexts/gl_includes.h rename to opendr/contexts/gl_includes.h diff --git a/cvwrap.py b/opendr/cvwrap.py similarity index 100% rename from cvwrap.py rename to opendr/cvwrap.py diff --git a/dummy.py b/opendr/dummy.py similarity index 100% rename from dummy.py rename to opendr/dummy.py diff --git a/everything.py b/opendr/everything.py similarity index 100% rename from everything.py rename to opendr/everything.py diff --git a/filters.py b/opendr/filters.py similarity index 100% rename from filters.py rename to opendr/filters.py diff --git a/geometry.py b/opendr/geometry.py similarity index 100% rename from geometry.py rename to opendr/geometry.py diff --git a/lighting.py b/opendr/lighting.py similarity index 100% rename from lighting.py rename to opendr/lighting.py diff --git a/renderer.py b/opendr/renderer.py similarity index 100% rename from renderer.py rename to opendr/renderer.py diff --git a/rogrenderer.py b/opendr/rogrenderer.py similarity index 100% rename from rogrenderer.py rename to opendr/rogrenderer.py diff --git a/serialization.py b/opendr/serialization.py similarity index 100% rename from serialization.py rename to opendr/serialization.py diff --git a/simple.py b/opendr/simple.py similarity index 100% rename from simple.py rename to opendr/simple.py diff --git a/slider_demo.py b/opendr/slider_demo.py similarity index 100% rename from slider_demo.py rename to opendr/slider_demo.py diff --git a/test_camera.py b/opendr/test_camera.py similarity index 100% rename from test_camera.py rename to opendr/test_camera.py diff --git a/test_depth_renderer.py b/opendr/test_depth_renderer.py similarity index 100% rename from test_depth_renderer.py rename to opendr/test_depth_renderer.py diff --git a/test_geometry.py b/opendr/test_geometry.py similarity index 100% rename from test_geometry.py rename to opendr/test_geometry.py diff --git a/test_renderer.py b/opendr/test_renderer.py similarity index 100% rename from test_renderer.py rename to opendr/test_renderer.py diff --git a/test_sh.py b/opendr/test_sh.py similarity index 100% rename from test_sh.py rename to opendr/test_sh.py diff --git a/topology.py b/opendr/topology.py similarity index 100% rename from topology.py rename to opendr/topology.py diff --git a/util_tests.py b/opendr/util_tests.py similarity index 100% rename from util_tests.py rename to opendr/util_tests.py diff --git a/utils.py b/opendr/utils.py similarity index 100% rename from utils.py rename to opendr/utils.py diff --git a/version.py b/opendr/version.py similarity index 73% rename from version.py rename to opendr/version.py index b53eadf..9e776ad 100644 --- a/version.py +++ b/opendr/version.py @@ -1,3 +1,3 @@ -version = '0.76' +version = '0.77' short_version = version full_version = version diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..61086fc --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,4 @@ +-r requirements.txt + +nose2>=0.5.0 +pylint>=1.5.4 diff --git a/setup.py b/setup.py index 2e2ca76..620fa1a 100644 --- a/setup.py +++ b/setup.py @@ -4,12 +4,19 @@ See LICENCE.txt for licensing and contact information. """ +try: + import pypandoc + long_description = pypandoc.convert('README.md', 'rst') +except (IOError, ImportError): + long_description = '' + print 'warning: pandoc or pypandoc does not seem to be installed; using empty long_description' + from setuptools import setup from distutils.extension import Extension import numpy import platform import os -from version import version +import importlib from pip.req import parse_requirements try: @@ -19,7 +26,7 @@ cythonize = lambda x : x have_cython = False -context_dir = os.path.join(os.path.dirname(__file__), 'contexts') +context_dir = os.path.join(os.path.dirname(__file__), 'opendr', 'contexts') osmesa_mirrors = [ 'https://s3.amazonaws.com/bodylabs-assets/public/osmesa/', @@ -41,7 +48,7 @@ def unzip(fname, dest_dir): z.extract(f, path=dest_dir) def download_zip(dest_fname): - from utils import wget + from opendr.utils import wget for base_url in osmesa_mirrors: print "Downloading %s" % (base_url + osmesa_fname, ) try: @@ -74,7 +81,7 @@ def autogen_opengl_sources(): sources = [ os.path.join(context_dir, x) for x in ['_constants.py', '_functions.pyx']] if not all([ os.path.exists(x) for x in sources ]): print "Autogenerating opengl sources" - from contexts import autogen + from opendr.contexts import autogen autogen.main() for x in sources: assert(os.path.exists(x)) @@ -86,14 +93,13 @@ def setup_opendr(ext_modules): ext_modules[0]._convert_pyx_sources_to_lang = lambda : None except: pass setup(name='opendr', - version=version, - packages = ['opendr', 'opendr.contexts', 'opendr.test_dr'], - package_dir = {'opendr': '.'}, + version=importlib.import_module('opendr').__version__, + packages = ['opendr', 'opendr.contexts'], author = 'Matthew Loper', author_email = 'matt.loper@gmail.com', url = 'http://github.com/mattloper/opendr', ext_package='opendr', - package_data={'opendr': ['test_dr/nasa*']}, + # package_data={'opendr': ['test_dr/nasa*']}, install_requires=install_requires, description='opendr', ext_modules=ext_modules, @@ -134,27 +140,27 @@ def mesa_ext(): extra_args.append('-Qunused-arguments') else: extra_args.append('-lstdc++') - return Extension("contexts.ctx_mesa", ['contexts/ctx_mesa.pyx'] if have_cython else ['contexts/ctx_mesa.c'], + return Extension("contexts.ctx_mesa", ['opendr/contexts/ctx_mesa.pyx'] if have_cython else ['opendr/contexts/ctx_mesa.c'], language="c", - library_dirs=['contexts/OSMesa/lib'], - depends=['contexts/_constants.py'], + library_dirs=['opendr/contexts/OSMesa/lib'], + depends=['opendr/contexts/_constants.py'], define_macros = [('__OSMESA__', 1)], - include_dirs=['.', numpy.get_include(), 'contexts/OSMesa/include'], + include_dirs=['.', numpy.get_include(), 'opendr/contexts/OSMesa/include'], libraries=libraries, extra_compile_args=extra_args, extra_link_args=extra_args) def mac_ext(): - return Extension("contexts.ctx_mac", ['contexts/ctx_mac.pyx', 'contexts/ctx_mac_internal.c'] if have_cython else ['contexts/ctx_mac.c', 'contexts/ctx_mac_internal.c'], + return Extension("contexts.ctx_mac", ['opendr/contexts/ctx_mac.pyx', 'opendr/contexts/ctx_mac_internal.c'] if have_cython else ['opendr/contexts/ctx_mac.c', 'opendr/contexts/ctx_mac_internal.c'], language="c", - depends=['contexts/_constants.py', 'contexts/ctx_mac_internal.h'], + depends=['opendr/contexts/_constants.py', 'opendr/contexts/ctx_mac_internal.h'], include_dirs=['.', numpy.get_include()], extra_compile_args=['-Qunused-arguments'], extra_link_args=['-Qunused-arguments']) def main(): - from contexts.fix_warnings import fix_warnings + from opendr.contexts.fix_warnings import fix_warnings fix_warnings() # Get osmesa and some processed files ready diff --git a/test_dr/Makefile b/test_dr/Makefile deleted file mode 100644 index 92ced23..0000000 --- a/test_dr/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -test: - env python -m unittest discover - - diff --git a/test_dr/__init__.py b/test_dr/__init__.py deleted file mode 100644 index e69de29..0000000 From ac1225125942a847c3e1bd7baec5a968c1300007 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Wed, 10 May 2017 15:45:58 -0400 Subject: [PATCH 51/56] fix some lint --- opendr/__init__.py | 8 +- opendr/camera.py | 57 +++++----- opendr/common.py | 89 ++++++++------- opendr/contexts/autogen.py | 106 +++++++++--------- opendr/contexts/draw_triangle_shaders_2_1.py | 53 +++++---- opendr/contexts/draw_triangle_shaders_3_2.py | 34 +++--- opendr/contexts/fix_warnings.py | 18 ++-- opendr/cvwrap.py | 4 +- opendr/dummy.py | 4 +- opendr/everything.py | 28 ++--- opendr/filters.py | 81 +++++++------- opendr/geometry.py | 90 ++++++++-------- opendr/lighting.py | 54 +++++----- opendr/renderer.py | 90 ++++++++-------- opendr/rogrenderer.py | 40 +++---- opendr/simple.py | 18 ++-- opendr/slider_demo.py | 24 ++--- opendr/test_camera.py | 26 ++--- opendr/test_depth_renderer.py | 2 +- opendr/test_geometry.py | 10 +- opendr/test_renderer.py | 70 ++++++------ opendr/test_sh.py | 71 ++++++------ opendr/topology.py | 108 +++++++++---------- opendr/util_tests.py | 15 ++- 24 files changed, 535 insertions(+), 565 deletions(-) diff --git a/opendr/__init__.py b/opendr/__init__.py index 603eebe..c41f8c6 100644 --- a/opendr/__init__.py +++ b/opendr/__init__.py @@ -1,4 +1,4 @@ -from version import version as __version__ +from opendr.version import version as __version__ def test(): from os.path import split @@ -6,7 +6,7 @@ def test(): test_loader = unittest.TestLoader() test_loader = test_loader.discover(split(__file__)[0]) test_runner = unittest.TextTestRunner() - test_runner.run( test_loader ) + test_runner.run(test_loader) demos = {} @@ -345,6 +345,6 @@ def demo(which=None): return print '- - - - - - - - - - - - - - - - - - - - - - -' - print re.sub('global.*\n','',demos[which]) + print re.sub('global.*\n', '', demos[which]) print '- - - - - - - - - - - - - - - - - - - - - - -\n' - exec('global np\n' + demos[which], globals(), locals()) + exec('global np\n' + demos[which], globals(), locals()) # pylint: disable=exec-used diff --git a/opendr/camera.py b/opendr/camera.py index 68ea11b..c5e1875 100755 --- a/opendr/camera.py +++ b/opendr/camera.py @@ -9,18 +9,18 @@ __all__ = ['ProjectPoints3D', 'ProjectPoints', 'RigidTransform'] -import chumpy as ch -from chumpy import depends_on, Ch -from cvwrap import cv2 import numpy as np import scipy.sparse as sp +import chumpy as ch +from chumpy import depends_on, Ch from chumpy.utils import row, col -from geometry import Rodrigues +from opendr.geometry import Rodrigues +from opendr.cvwrap import cv2 def RigidTransformSlow(**kwargs): # Returns a Ch object with dterms 'v', 'rt', and 't' - result = Ch(lambda v, rt, t : v.dot(Rodrigues(rt=rt)) + t) + result = Ch(lambda v, rt, t: v.dot(Rodrigues(rt=rt)) + t) if len(kwargs) > 0: result.set(**kwargs) return result @@ -28,61 +28,60 @@ def RigidTransformSlow(**kwargs): class RigidTransform(Ch): dterms = 'v', 'rt', 't' - + def compute_r(self): return (cv2.Rodrigues(self.rt.r)[0].dot(self.v.r.T) + col(self.t.r)).T.copy() - + def compute_dr_wrt(self, wrt): if wrt not in (self.v, self.rt, self.t): return - + if wrt is self.t: - if not hasattr(self, '_drt') or self._drt.shape[0] != self.v.r.size: + if not hasattr(self, '_drt') or self._drt.shape[0] != self.v.r.size: IS = np.arange(self.v.r.size) JS = IS % 3 data = np.ones(len(IS)) self._drt = sp.csc_matrix((data, (IS, JS))) return self._drt - + if wrt is self.rt: rot, rot_dr = cv2.Rodrigues(self.rt.r) - rot_dr = rot_dr.reshape((3,3,3)) - dr = np.einsum('abc, zc -> zba', rot_dr, self.v.r).reshape((-1,3)) + rot_dr = rot_dr.reshape((3, 3, 3)) + dr = np.einsum('abc, zc -> zba', rot_dr, self.v.r).reshape((-1, 3)) return dr - + if wrt is self.v: rot = cv2.Rodrigues(self.rt.r)[0] - + IS = np.repeat(np.arange(self.v.r.size), 3) - JS = np.repeat(np.arange(self.v.r.size).reshape((-1,3)), 3, axis=0) + JS = np.repeat(np.arange(self.v.r.size).reshape((-1, 3)), 3, axis=0) data = np.vstack([rot for i in range(self.v.r.size/3)]) result = sp.csc_matrix((data.ravel(), (IS.ravel(), JS.ravel()))) return result - class ProjectPoints(Ch): dterms = 'v', 'rt', 't', 'f', 'c', 'k' def is_valid(self): if any([len(v.r.shape) > 1 for v in [self.rt, self.t, self.f, self.c, self.k]]): return False, 'rt, t, f, c, and k must be 1D' - + if any([v.r.size != 3 for v in [self.rt, self.t]]): return False, 'rt and t must have size=3' - + if any([v.r.size != 2 for v in [self.f, self.c]]): return False, 'f and c must have size=2' - return True, '' + return True, '' def compute_r(self): #return self.r_and_derivatives[0].squeeze() #return self.get_r_and_derivatives(self.v.r, self.rt.r, self.t.r, self.f.r, self.c.r, self.k.r)[0].squeeze() # method self.r_and_derivatives will compute derivatives as well #see http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html - v_t = self.v.r.reshape((-1,3)).copy() + v_t = self.v.r.reshape((-1, 3)).copy() if np.any(self.rt.r != 0.): v_t = (v_t).dot(cv2.Rodrigues(self.rt.r)[0].T) if np.any(self.t.r != 0.): @@ -93,7 +92,7 @@ def compute_r(self): if np.any(self.k.r != 0.): k = self.k.r # According to this link: http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html - # k can have three lengths: (k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]]) + # k can have three lengths: (k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]]) if len(k) == 4: k1, k2, p1, p2 = k elif len(k) == 5: @@ -115,7 +114,7 @@ def compute_r(self): def compute_dr_wrt(self, wrt): if wrt not in [self.v, self.rt, self.t, self.f, self.c, self.k]: return None - + j = self.r_and_derivatives[1] if wrt is self.rt: return j[:, :3] @@ -165,7 +164,7 @@ def project_depth_point(self, xyz): uvd = cam.camera_mtx.dot(xyz) uv = uvd[:2] / uvd[-1] return uv - + @depends_on('f','c') def camera_mtx(self): return np.array([[self.f.r[0], 0, self.c.r[0]],[0., self.f.r[1], self.c.r[1]],[0.,0.,1.]], dtype=np.float64) @@ -174,18 +173,18 @@ def camera_mtx(self): def view_mtx(self): R = cv2.Rodrigues(self.rt.r)[0] return np.hstack((R,col(self.t.r))) - + @depends_on('v', 'rt', 't', 'f', 'c', 'k') def r_and_derivatives(self): v = self.v.r.reshape((-1,3)).copy() return cv2.projectPoints(v, self.rt.r, self.t.r, self.camera_mtx, self.k.r) - + @property def view_matrix(self): R = cv2.Rodrigues(self.rt.r)[0] return np.hstack((R, col(self.t.r))) - + class ProjectPoints3D(ProjectPoints): dterms = 'v', 'rt', 't', 'f', 'c', 'k' @@ -221,9 +220,8 @@ def compute_dr_wrt(self, wrt): result = bigger.reshape((-1, bigger.shape[-1])) - return result - - + return result + def main(): import unittest @@ -234,4 +232,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/opendr/common.py b/opendr/common.py index 978cc75..02bdd15 100755 --- a/opendr/common.py +++ b/opendr/common.py @@ -17,7 +17,7 @@ from numpy import nanmean as nanmean_impl from chumpy.utils import row, col -from contexts._constants import * +from contexts._constants import * # pylint: disable=unused-wildcard-import def nanmean(a, axis): # don't call nan_to_num in here, unless you check that @@ -26,12 +26,12 @@ def nanmean(a, axis): return result def nangradients(arr): - dy = np.expand_dims(arr[:-1,:,:] - arr[1:,:,:], axis=3) - dx = np.expand_dims(arr[:,:-1,:] - arr[:, 1:, :], axis=3) + dy = np.expand_dims(arr[:-1, :, :] - arr[1:, :, :], axis=3) + dx = np.expand_dims(arr[:, :-1, :] - arr[:, 1:, :], axis=3) - dy = np.concatenate((dy[1:,:,:], dy[:-1,:,:]), axis=3) + dy = np.concatenate((dy[1:, :, :], dy[:-1, :, :]), axis=3) dy = nanmean(dy, axis=3) - dx = np.concatenate((dx[:,1:,:], dx[:,:-1,:]), axis=3) + dx = np.concatenate((dx[:, 1:, :], dx[:, :-1, :]), axis=3) dx = nanmean(dx, axis=3) if arr.shape[2] > 1: @@ -40,8 +40,8 @@ def nangradients(arr): gy, gx = np.gradient(arr.squeeze()) gy = np.atleast_3d(gy) gx = np.atleast_3d(gx) - gy[1:-1,:,:] = -dy - gx[:,1:-1,:] = -dx + gy[1:-1, :, :] = -dy + gx[:, 1:-1, :] = -dx return gy, gx @@ -71,10 +71,10 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid ksize = 1 bndf = bnd_bool.astype(np.float64) nbndf = np.logical_not(bnd_bool).astype(np.float64) - sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5,5] + sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5, 5] bnd_nan = bndf.reshape((observed.shape[0], observed.shape[1], -1)).copy() - bnd_nan.ravel()[bnd_nan.ravel()>0] = np.nan + bnd_nan.ravel()[bnd_nan.ravel() > 0] = np.nan bnd_nan += 1 obs_nonbnd = np.atleast_3d(observed) * bnd_nan @@ -167,9 +167,9 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid dxs = xdiff[pys, pxs, k] dys = ydiff[pys, pxs, k] if f.shape[1] == 3: - datas.append(np.hstack((col(dxs)*bc0,col(dys)*bc0,col(dxs)*bc1,col(dys)*bc1,col(dxs)*bc2,col(dys)*bc2)).ravel()) + datas.append(np.hstack((col(dxs)*bc0, col(dys)*bc0, col(dxs)*bc1, col(dys)*bc1, col(dxs)*bc2, col(dys)*bc2)).ravel()) else: - datas.append(np.hstack((col(dxs)*bc0,col(dys)*bc0,col(dxs)*bc1,col(dys)*bc1)).ravel()) + datas.append(np.hstack((col(dxs)*bc0, col(dys)*bc0, col(dxs)*bc1, col(dys)*bc1)).ravel()) data = np.concatenate(datas) @@ -201,8 +201,8 @@ def dImage_wrt_2dVerts(observed, visible, visibility, barycentric, image_width, JS = np.concatenate([JS for i in range(n_channels)]) # Step 2: get the data ready, ie the actual values of the derivatives - ksize=1 - sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5,5] + ksize = 1 + sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5, 5] xdiff = -cv2.Sobel(observed, cv2.CV_64F, dx=1, dy=0, ksize=ksize) / sobel_normalizer ydiff = -cv2.Sobel(observed, cv2.CV_64F, dx=0, dy=1, ksize=ksize) / sobel_normalizer @@ -219,9 +219,9 @@ def dImage_wrt_2dVerts(observed, visible, visibility, barycentric, image_width, dxs = xdiff[pys, pxs, k] dys = ydiff[pys, pxs, k] if f.shape[1] == 3: - datas.append(np.hstack((col(dxs)*bc0,col(dys)*bc0,col(dxs)*bc1,col(dys)*bc1,col(dxs)*bc2,col(dys)*bc2)).ravel()) + datas.append(np.hstack((col(dxs)*bc0, col(dys)*bc0, col(dxs)*bc1, col(dys)*bc1, col(dxs)*bc2, col(dys)*bc2)).ravel()) else: - datas.append(np.hstack((col(dxs)*bc0,col(dys)*bc0,col(dxs)*bc1,col(dys)*bc1)).ravel()) + datas.append(np.hstack((col(dxs)*bc0, col(dys)*bc0, col(dxs)*bc1, col(dys)*bc1)).ravel()) data = np.concatenate(datas) @@ -236,8 +236,8 @@ def flow_to(self, v_next, cam_next): color_image = self.r visibility = self.visibility_image pxpos = np.zeros_like(self.color_image) - pxpos[:,:,0] = np.tile(row(np.arange(self.color_image.shape[1])), (self.color_image.shape[0], 1)) - pxpos[:,:,2] = np.tile(col(np.arange(self.color_image.shape[0])), (1, self.color_image.shape[1])) + pxpos[:, :, 0] = np.tile(row(np.arange(self.color_image.shape[1])), (self.color_image.shape[0], 1)) + pxpos[:, :, 2] = np.tile(col(np.arange(self.color_image.shape[0])), (1, self.color_image.shape[1])) visible = np.nonzero(visibility.ravel() != 4294967295)[0] num_visible = len(visible) @@ -272,7 +272,7 @@ def flow_to(self, v_next, cam_next): n_channels = self.camera.shape[1] flow = r2 - r1 - flow_im = np.zeros((self.frustum['height'], self.frustum['width'], n_channels)).reshape((-1,n_channels)) + flow_im = np.zeros((self.frustum['height'], self.frustum['width'], n_channels)).reshape((-1, n_channels)) flow_im[visible] = flow flow_im = flow_im.reshape((self.frustum['height'], self.frustum['width'], n_channels)) @@ -306,8 +306,8 @@ def dr_wrt_vc(visible, visibility, f, barycentric, frustum, vc_size, num_channel IS = np.tile(col(visible), (1, 3)).ravel() JS = col(f[visibility.ravel()[visible]].ravel()) - bc = barycentric.reshape((-1,3)) - data = np.asarray(bc[visible,:], order='C').ravel() + bc = barycentric.reshape((-1, 3)) + data = np.asarray(bc[visible, :], order='C').ravel() IS = np.concatenate([IS*num_channels+k for k in range(num_channels)]) JS = np.concatenate([JS*num_channels+k for k in range(num_channels)]) @@ -340,7 +340,7 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, y rr = result.ravel() faces_to_draw = np.unique(rr[rr != 4294967295]) - if len(faces_to_draw)==0: + if len(faces_to_draw) == 0: result = np.ones((gl.height, gl.width)).astype(np.uint32)*4294967295 return result gl.PolygonMode(GL_FRONT_AND_BACK, GL_LINE) @@ -360,7 +360,7 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, y result2[idxs] = faces_to_draw[result2[idxs]] if False: - result2[result2==4294967295] = 0 + result2[result2 == 4294967295] = 0 import matplotlib.pyplot as plt result2 = result2.reshape(result.shape[:2]) plt.figure() @@ -377,29 +377,29 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, y def draw_visibility_image_internal(gl, v, f): """Assumes camera is set up correctly in gl context.""" - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) fc = np.arange(1, len(f)+1) fc = np.tile(col(fc), (1, 3)) fc[:, 0] = fc[:, 0] & 255 - fc[:, 1] = (fc[:, 1] >> 8 ) & 255 - fc[:, 2] = (fc[:, 2] >> 16 ) & 255 + fc[:, 1] = (fc[:, 1] >> 8) & 255 + fc[:, 2] = (fc[:, 2] >> 16) & 255 fc = np.asarray(fc, dtype=np.uint8) draw_colored_primitives(gl, v, f, fc) raw = np.asarray(gl.getImage(), np.uint32) - raw = raw[:,:,0] + raw[:,:,1]*256 + raw[:,:,2]*256*256 - 1 + raw = raw[:, :, 0] + raw[:, :, 1]*256 + raw[:, :, 2]*256*256 - 1 return raw # this assumes that fc is either "by faces" or "verts by face", not "by verts" def draw_colored_primitives(gl, v, f, fc=None): - gl.EnableClientState(GL_VERTEX_ARRAY); + gl.EnableClientState(GL_VERTEX_ARRAY) verts_by_face = np.asarray(v.reshape((-1,3))[f.ravel()], dtype=np.float64, order='C') gl.VertexPointer(verts_by_face) if fc is not None: - gl.EnableClientState(GL_COLOR_ARRAY); + gl.EnableClientState(GL_COLOR_ARRAY) if fc.size == verts_by_face.size: vc_by_face = fc else: @@ -408,19 +408,19 @@ def draw_colored_primitives(gl, v, f, fc=None): if vc_by_face.size != verts_by_face.size: raise Exception('fc must have either rows=(#rows in faces) or rows=(# elements in faces)') - if isinstance(fc[0,0], np.float64): + if isinstance(fc[0, 0], np.float64): vc_by_face = np.asarray(vc_by_face, dtype=np.float64, order='C') gl.ColorPointerd(vc_by_face) - elif isinstance(fc[0,0], np.uint8): + elif isinstance(fc[0, 0], np.uint8): vc_by_face = np.asarray(vc_by_face, dtype=np.uint8, order='C') gl.ColorPointerub(vc_by_face) else: raise Exception('Unknown color type for fc') else: - gl.DisableClientState(GL_COLOR_ARRAY); + gl.DisableClientState(GL_COLOR_ARRAY) - if f.shape[1]==2: + if f.shape[1] == 2: primtype = GL_LINES else: primtype = GL_TRIANGLES @@ -428,7 +428,7 @@ def draw_colored_primitives(gl, v, f, fc=None): if primtype == GL_LINES: f = np.fliplr(f).copy() - verts_by_edge = v.reshape((-1,3))[f.ravel()] + verts_by_edge = v.reshape((-1, 3))[f.ravel()] verts_by_edge = np.asarray(verts_by_edge, dtype=np.float64, order='C') gl.VertexPointer(verts_by_edge) gl.DrawElements(GL_LINES, np.arange(f.size, dtype=np.uint32).ravel()) @@ -439,12 +439,12 @@ def draw_texcoord_image(glf, v, f, vt, ft, boundarybool_image=None): gl.Disable(GL_TEXTURE_2D) gl.DisableClientState(GL_TEXTURE_COORD_ARRAY) - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # want vtc: texture-coordinates per vertex (not per element in vc) colors = vt[ft.ravel()] - colors = np.asarray(np.hstack((colors, col(colors[:,0]*0))), np.float64, order='C') + colors = np.asarray(np.hstack((colors, col(colors[:, 0]*0))), np.float64, order='C') draw_colored_primitives(gl, v, f, colors) if boundarybool_image is not None: @@ -452,8 +452,8 @@ def draw_texcoord_image(glf, v, f, vt, ft, boundarybool_image=None): draw_colored_primitives(gl, v, f, colors) gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) - result = np.asarray(deepcopy(gl.getImage()), np.float64, order='C')[:,:,:2].copy() - result[:,:,1] = 1. - result[:,:,1] + result = np.asarray(deepcopy(gl.getImage()), np.float64, order='C')[:, :, :2].copy() + result[:, :, 1] = 1. - result[:, :, 1] return result @@ -488,17 +488,17 @@ def draw_barycentric_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, def draw_barycentric_image_internal(gl, v, f): - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - gl.EnableClientState(GL_VERTEX_ARRAY); - gl.EnableClientState(GL_COLOR_ARRAY); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + gl.EnableClientState(GL_VERTEX_ARRAY) + gl.EnableClientState(GL_COLOR_ARRAY) - verts_by_face = v.reshape((-1,3))[f.ravel()] + verts_by_face = v.reshape((-1, 3))[f.ravel()] verts_by_face = np.asarray(verts_by_face, dtype=np.float64, order='C') vc_by_face = np.asarray(np.tile(np.eye(3)[:f.shape[1], :], (verts_by_face.shape[0]/f.shape[1], 1)), order='C') gl.ColorPointerd(vc_by_face) gl.VertexPointer(verts_by_face) - gl.DrawElements(GL_TRIANGLES if f.shape[1]==3 else GL_LINES, np.arange(f.size, dtype=np.uint32).ravel()) + gl.DrawElements(GL_TRIANGLES if f.shape[1] == 3 else GL_LINES, np.arange(f.size, dtype=np.uint32).ravel()) result = np.asarray(deepcopy(gl.getImage()), np.float64) return result @@ -520,7 +520,7 @@ def get_inbetween_boundaries(self): w-1, h, near, far, camera.view_matrix, camera.k) - bnd_x = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:,:-1] + bnd_x = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:, :-1] self.glb.Viewport(0, 0, w, h-1) _setup_camera(self.glb, @@ -529,10 +529,9 @@ def get_inbetween_boundaries(self): w, h-1, near, far, camera.view_matrix, camera.k) - bnd_y = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:-1,:] + bnd_y = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:-1, :] # Put things back to normal self.glb.Viewport(0, 0, w, h) setup_camera(self.glb, camera, frustum) return bnd_x, bnd_y - diff --git a/opendr/contexts/autogen.py b/opendr/contexts/autogen.py index 502404e..8d1e665 100755 --- a/opendr/contexts/autogen.py +++ b/opendr/contexts/autogen.py @@ -8,11 +8,8 @@ """ -import sys -import os import re from os.path import split, join -import platform def main(): @@ -27,58 +24,58 @@ def main(): functions = 'cdef extern from "gl_includes.h":\n' #extfunctions = 'cdef extern from "GL/glext.h":\n' extfunctions = '' - + text = open(split(__file__)[0] + '/OSMesa/include/GL/gl.h').read().replace('const', '') text += '\ntypedef char GLchar;\n' - defines = re.findall('#define GL_(.*?)\s+(.*?)\n', text, flags=re.DOTALL) - defines += re.findall('#define GL_(.*?)\s+(.*?)\n', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - funcs = re.findall('GLAPI (\w+) GLAPIENTRY gl(\w+)\s*\((.*?)\);', text, flags=re.DOTALL) - - extfuncs = re.findall('GLAPI (void) APIENTRY gl(Generate\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(GenBuffer\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(BindBuffer\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(BufferData)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - - extfuncs += re.findall('GLAPI (void) APIENTRY gl(GenVertexArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(BindVertexArray)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(VertexAttrib4fv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(DrawArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(DeleteVertexArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(ClearBufferfv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(EnableVertexAttribArray)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(VertexAttribPointer)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - - extfuncs += re.findall('GLAPI (void) APIENTRY gl(ValidateProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(GetProgramInfoLog)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(DeleteProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (GLuint) APIENTRY gl(CreateProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (GLuint) APIENTRY gl(CreateShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(ShaderSource)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(CompileShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(AttachShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(LinkProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(UseProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (GLint) APIENTRY gl(GetUniformLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(Uniform1i)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(Uniform4f)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(Uniform1f)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (GLint) APIENTRY gl(GetAttribLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(BindFragDataLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - extfuncs += re.findall('GLAPI (void) APIENTRY gl(UniformMatrix4fv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) - - - - typedefs = re.findall('typedef (\w[^\n]+GL\w+);', text, flags=re.DOTALL) - typedefs += re.findall('typedef (\w[^\n]+GL\w+ptr);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + defines = re.findall(r'#define GL_(.*?)\s+(.*?)\n', text, flags=re.DOTALL) + defines += re.findall(r'#define GL_(.*?)\s+(.*?)\n', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + funcs = re.findall(r'GLAPI (\w+) GLAPIENTRY gl(\w+)\s*\((.*?)\);', text, flags=re.DOTALL) + + extfuncs = re.findall(r'GLAPI (void) APIENTRY gl(Generate\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(GenBuffer\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(BindBuffer\w*)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(BufferData)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(GenVertexArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(BindVertexArray)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(VertexAttrib4fv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(DrawArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(DeleteVertexArrays)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(ClearBufferfv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(EnableVertexAttribArray)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(VertexAttribPointer)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(ValidateProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(GetProgramInfoLog)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(DeleteProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (GLuint) APIENTRY gl(CreateProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (GLuint) APIENTRY gl(CreateShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(ShaderSource)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(CompileShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(AttachShader)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(LinkProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(UseProgram)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (GLint) APIENTRY gl(GetUniformLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(Uniform1i)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(Uniform4f)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(Uniform1f)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (GLint) APIENTRY gl(GetAttribLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(BindFragDataLocation)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + extfuncs += re.findall(r'GLAPI (void) APIENTRY gl(UniformMatrix4fv)\s*\((.*?)\);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) + + + + typedefs = re.findall(r'typedef (\w[^\n]+GL\w+);', text, flags=re.DOTALL) + typedefs += re.findall(r'typedef (\w[^\n]+GL\w+ptr);', open(split(__file__)[0] + '/OSMesa/include/GL/glext.h').read().replace('const', ''), flags=re.DOTALL) constants_all = '' for define in defines: if 'INVALID_INDEX' not in define[0] and 'TIMEOUT_IGNORED' not in define[0]: constants += 'GL_%s = %s\n' % (define[0], define[1]) constants_all += "'GL_%s'," % (define[0]) - + for typedef in typedefs: functions += '\tctypedef %s\n' % (typedef,) - + for func in funcs: args = func[2] if args.strip() == 'void': @@ -90,7 +87,7 @@ def main(): if 'GLhandleARB' in args or 'GLhandleARB' in func[0]: continue args = args.replace(' in,', 'inp,') - + nogil = '' if ('*' in args and func[1] != 'ReadPixels') else 'nogil' functions += '\tcdef %s _gl%s "gl%s"(%s) %s\n' % (func[0], func[1], func[1], args, nogil) @@ -107,18 +104,18 @@ def main(): args = args.replace(' in,', 'inp,') nogil = '' if '*' in args else 'nogil' extfunctions += '\tcdef %s _gl%s "gl%s"(%s) %s\n' % (func[0], func[1], func[1], args, nogil) - # for t in text.split('\n'): + # for t in text.split('\n'): # if t.startswith('#define GL_'): # m = re.match(r"#define (GL_\w+)\s*(\w+)",t) # constants += '%s = %s\n' % (m.group(1), m.group(2)) # exports.append(m.group(1)) - # + # # if t.startswith('typedef'): # try: - # m = re.match(r"typedef (\w+\s.*GL\w+);",t) + # m = re.match(r"typedef (\w+\s.*GL\w+);",t) # functions += '\tctypedef %s\n' % (m.group(1)) # except: pass - # + # # if 'ReadPixels' in t: # import pdb; pdb.set_trace() # if t.startswith('GLAPI void GLAPIENTRY gl'): @@ -127,15 +124,15 @@ def main(): # returntype = m.group(1) # funcname = m.group(2) # fargs = m.group(3) - # + # # if fargs.strip() == 'void': # fargs = '' # if 'GLprogramcallbackMESA' not in fargs: # functions += '\tcdef %s _gl%s "gl%s"(%s)\n' % (returntype, funcname, funcname, fargs) # except: pass - # + # # text = open(split(__file__)[0] + '/include/GL/glu.h').read().replace('const','') - # for t in text.split('\n'): + # for t in text.split('\n'): # if t.startswith('#define GLU_'): # m = re.match(r"#define (GLU_\w+)\s*(\w+)",t) # constants += '%s = %s\n' % (m.group(1), m.group(2)) @@ -157,4 +154,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/opendr/contexts/draw_triangle_shaders_2_1.py b/opendr/contexts/draw_triangle_shaders_2_1.py index 8ffd068..260d700 100644 --- a/opendr/contexts/draw_triangle_shaders_2_1.py +++ b/opendr/contexts/draw_triangle_shaders_2_1.py @@ -1,14 +1,14 @@ __author__ = 'matt' +import platform import cv2 import numpy as np -from opendr.contexts._constants import * +from opendr.contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import -import platform -if platform.system()=='Darwin': - from ctx_mac import OsContext +if platform.system() == 'Darwin': + from opendr.contexts.ctx_mac import OsContext # pylint: disable=no-name-in-module else: - from ctx_mesa import OsContext + from opendr.contexts.ctx_mesa import OsContext # pylint: disable=no-name-in-module fs_source = """ #version 120 @@ -33,40 +33,39 @@ def main(): gl.Viewport(0, 0, w, h) gl.MatrixMode(GL_PROJECTION) - gl.LoadIdentity(); + gl.LoadIdentity() - gl.MatrixMode(GL_MODELVIEW); + gl.MatrixMode(GL_MODELVIEW) gl.LoadIdentity() gl.Enable(GL_DEPTH_TEST) gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) - gl.Disable(GL_LIGHTING); + gl.Disable(GL_LIGHTING) gl.Disable(GL_CULL_FACE) - gl.PixelStorei(GL_PACK_ALIGNMENT,1) - gl.PixelStorei(GL_UNPACK_ALIGNMENT,1) + gl.PixelStorei(GL_PACK_ALIGNMENT, 1) + gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1) gl.Clear(GL_COLOR_BUFFER_BIT) gl.Clear(GL_DEPTH_BUFFER_BIT) - v = np.random.rand(9).reshape((-1,3)) + v = np.random.rand(9).reshape((-1, 3)) f = np.arange(v.size, dtype=np.uint32) gl.EnableClientState(GL_VERTEX_ARRAY) gl.VertexPointer(v) - if True: - program = gl.CreateProgram() - fs = gl.CreateShader(GL_FRAGMENT_SHADER) - gl.ShaderSource(fs, 1, fs_source, len(fs_source)) - vs = gl.CreateShader(GL_VERTEX_SHADER) - gl.ShaderSource(vs, 1, vs_source, len(vs_source)) - gl.AttachShader(program, vs) - gl.AttachShader(program, fs) - gl.LinkProgram(program) - gl.UseProgram(program) + program = gl.CreateProgram() + fs = gl.CreateShader(GL_FRAGMENT_SHADER) + gl.ShaderSource(fs, 1, fs_source, len(fs_source)) + vs = gl.CreateShader(GL_VERTEX_SHADER) + gl.ShaderSource(vs, 1, vs_source, len(vs_source)) + gl.AttachShader(program, vs) + gl.AttachShader(program, fs) + gl.LinkProgram(program) + gl.UseProgram(program) - print 'glValidateProgram: ' + str(gl.ValidateProgram(program)) - print 'glGetProgramInfoLog ' + str(gl.GetProgramInfoLog(program)) - print 'GL_MAX_VERTEX_ATTRIBS: ' + str(gl.GetInteger(GL_MAX_VERTEX_ATTRIBS)) + print 'glValidateProgram: ' + str(gl.ValidateProgram(program)) + print 'glGetProgramInfoLog ' + str(gl.GetProgramInfoLog(program)) + print 'GL_MAX_VERTEX_ATTRIBS: ' + str(gl.GetInteger(GL_MAX_VERTEX_ATTRIBS)) gl.DrawElements(GL_TRIANGLES, f) @@ -76,9 +75,5 @@ def main(): # import pdb; pdb.set_trace() - - - - if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/opendr/contexts/draw_triangle_shaders_3_2.py b/opendr/contexts/draw_triangle_shaders_3_2.py index 6665d99..b93bca8 100644 --- a/opendr/contexts/draw_triangle_shaders_3_2.py +++ b/opendr/contexts/draw_triangle_shaders_3_2.py @@ -1,14 +1,14 @@ __author__ = 'matt' +import platform import cv2 import numpy as np -from opendr.contexts._constants import * +from opendr.contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import -import platform -if platform.system()=='Darwin': - from ctx_mac import OsContext +if platform.system() == 'Darwin': + from opendr.contexts.ctx_mac import OsContext # pylint: disable=no-name-in-module else: - from ctx_mesa import OsContext + from opendr.contexts.ctx_mesa import OsContext # pylint: disable=no-name-in-module fs_source = """ #version 150 @@ -60,13 +60,13 @@ def main(): gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) # gl.Disable(GL_LIGHTING); # causes error gl.Disable(GL_CULL_FACE) - gl.PixelStorei(GL_PACK_ALIGNMENT,1) - gl.PixelStorei(GL_UNPACK_ALIGNMENT,1) + gl.PixelStorei(GL_PACK_ALIGNMENT, 1) + gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1) gl.Clear(GL_COLOR_BUFFER_BIT) gl.Clear(GL_DEPTH_BUFFER_BIT) - vertices = np.random.rand(9).reshape((-1,3)).ravel() + vertices = np.random.rand(9).reshape((-1, 3)).ravel() #vertices = np.ones(9) * .5 #vertices = np.arange(9).astype(np.float64) colors = np.ones_like(vertices).ravel() @@ -89,10 +89,10 @@ def main(): gl.LinkProgram(program) - vertexLoc = gl.GetAttribLocation(program,"position") - colorLoc = gl.GetAttribLocation(program,"color") - projMatrixLoc = gl.GetUniformLocation(program, "projMatrix"); - viewMatrixLoc = gl.GetUniformLocation(program, "viewMatrix"); + vertexLoc = gl.GetAttribLocation(program, "position") + colorLoc = gl.GetAttribLocation(program, "color") + projMatrixLoc = gl.GetUniformLocation(program, "projMatrix") + viewMatrixLoc = gl.GetUniformLocation(program, "viewMatrix") gl.UseProgram(program) @@ -122,8 +122,8 @@ def main(): # PROJECTION MATRICES projMatrix = np.eye(4, dtype=np.float32) viewMatrix = np.eye(4, dtype=np.float32) - gl.UniformMatrix4fv(projMatrixLoc, 1, 0, projMatrix) - gl.UniformMatrix4fv(viewMatrixLoc, 1, 0, viewMatrix) + gl.UniformMatrix4fv(projMatrixLoc, 1, 0, projMatrix) + gl.UniformMatrix4fv(viewMatrixLoc, 1, 0, viewMatrix) ############################### @@ -141,9 +141,5 @@ def main(): # import pdb; pdb.set_trace() - - - - if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/opendr/contexts/fix_warnings.py b/opendr/contexts/fix_warnings.py index 1ddf556..8d69fa2 100644 --- a/opendr/contexts/fix_warnings.py +++ b/opendr/contexts/fix_warnings.py @@ -2,16 +2,16 @@ def fix_warnings(): import platform if platform.system() == 'Darwin': # Get rid of various flags that cause warnings and/or errors + flags_to_remove = [ + '-Wstrict-prototypes', + '-arch i386', + '-mno-fused-madd', + ] import distutils.sysconfig as ds import string a = ds.get_config_vars() for k, v in a.items(): - try: - if string.find(v, '-Wstrict-prototypes') != -1: - a[k] = string.replace(v, '-Wstrict-prototypes', '') - if string.find(v, '-arch i386') != -1: - a[k] = string.replace(v, '-arch i386', '') - if string.find(v, '-mno-fused-madd ') != -1: - a[k] = string.replace(v, '-mno-fused-madd', '') - except: - pass \ No newline at end of file + for flag in flags_to_remove: + if isinstance(v, basestring) and flag in v: + # print "found", flag, "in", k + a[k] = string.replace(v, flag, '') diff --git a/opendr/cvwrap.py b/opendr/cvwrap.py index b6e38e4..bb033c5 100644 --- a/opendr/cvwrap.py +++ b/opendr/cvwrap.py @@ -1,4 +1,4 @@ try: - import cv2 + import cv2 # pylint: disable=unused-import except: - raise Exception('Failed to import cv2 from the OpenCV distribution. Please install OpenCV with Python support. OpenCV may either be installed from http://opencv.org or installed with package managers such as Homebrew (on Mac, http://brew.sh) or apt-get (on Ubuntu or Debian).') \ No newline at end of file + raise Exception('Failed to import cv2 from the OpenCV distribution. Please install OpenCV with Python support. OpenCV may either be installed from http://opencv.org or installed with package managers such as Homebrew (on Mac, http://brew.sh) or apt-get (on Ubuntu or Debian).') diff --git a/opendr/dummy.py b/opendr/dummy.py index 4005759..28c0712 100755 --- a/opendr/dummy.py +++ b/opendr/dummy.py @@ -10,7 +10,7 @@ class Dummy(object): def __getattr__(self, name): - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs): # pylint: disable=unused-argument pass return wrapper @@ -19,4 +19,4 @@ def wrapper(*args, **kwargs): class Minimal(object): def __init__(self, **kwargs): - self.__dict__ = kwargs \ No newline at end of file + self.__dict__ = kwargs diff --git a/opendr/everything.py b/opendr/everything.py index fd652ba..8b07c66 100644 --- a/opendr/everything.py +++ b/opendr/everything.py @@ -1,29 +1,29 @@ __all__ = [] -import camera -from camera import * +import opendr.camera +from opendr.camera import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += camera.__all__ -import renderer -from renderer import * +import opendr.renderer +from opendr.renderer import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += renderer.__all__ -import lighting -from lighting import * +import opendr.lighting +from opendr.lighting import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += lighting.__all__ -import topology -from topology import * +import opendr.topology +from opendr.topology import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += topology.__all__ -import geometry -from geometry import * +import opendr.geometry +from opendr.geometry import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += geometry.__all__ -import serialization -from serialization import * +import opendr.serialization +from opendr.serialization import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += serialization.__all__ -import filters -from filters import * +import opendr.filters +from opendr.filters import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += filters.__all__ diff --git a/opendr/filters.py b/opendr/filters.py index 586eb56..ae45a91 100755 --- a/opendr/filters.py +++ b/opendr/filters.py @@ -15,7 +15,6 @@ import scipy.sparse as sp from chumpy.ch import MatVecMult, Ch, depends_on - def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list): @@ -29,10 +28,10 @@ def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list norm2 = normalization imshape = [int(x) for x in imshape] - + output_objs = [] for level in range(n_levels): - + blur_mtx = filter_for(imshape[0], imshape[1], imshape[2] if len(imshape)>2 else 1, kernel = GaussianKernel2D(3, 1)) blurred = MatVecMult(blur_mtx, input_objective).reshape(imshape) output_objs.append(norm2(input_objective - blurred)) @@ -40,15 +39,15 @@ def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list halfsampler_mtx, imshape = halfsampler_for(imshape) input_objective = MatVecMult(halfsampler_mtx, blurred.ravel()).reshape(imshape) - - output_objs.append(norm2(input_objective).reshape(imshape)) - + + output_objs.append(norm2(input_objective).reshape(imshape)) + return output_objs if as_list else reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), output_objs) def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_levels=3, as_list=False, label=None): - + if imshape is None: imshape = input_objective.shape @@ -67,11 +66,11 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level input_objective = norm2(input_objective) output_objectives = [input_objective] - for ik in range(n_levels): + for ik in range(n_levels): cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape) cur_imshape = cur_obj.output_shape output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label,ik)) - + if not as_list: andit = lambda a : reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), a) output_objectives = andit(output_objectives) @@ -90,14 +89,14 @@ def GaussianKernel2D(ksize, sigma): class GaussPyrDownOneOld(Ch): terms = 'im_shape', 'want_downsampling', 'kernel' dterms = 'px' - + # Approximation to a 3x3 Gaussian kernel default_kernel = GaussianKernel2D(3, 1) def on_changed(self, which): if not hasattr(self, 'kernel'): self.kernel = self.default_kernel.copy() - + if 'im_shape' in which: sh = self.im_shape self.transf_mtx, self._output_shape = filter_for_nopadding(sh, self.kernel) @@ -108,36 +107,36 @@ def on_changed(self, which): if 'px' in which: self.transform.vec = self.px - - + + @property def output_shape(self): self._call_on_changed() # trigger changes from im_shape return self._output_shape - + def compute_r(self): result = self.transf_mtx.dot(self.px.r.ravel()).reshape(self.output_shape) #print result.shape return result - + def compute_dr_wrt(self, wrt): if wrt is self.transform: return 1 - - + + class GaussPyrDownOneNew(Ch): terms = 'im_shape' dterms = 'px' - + @property def output_shape(self): return self.r.shape - + def compute_r(self): result = cv2.pyrDown(self.px.r) return result - + def compute_dr_wrt(self, wrt): if wrt is self.px: linop = lambda x : cv2.pyrDown(x.reshape(self.im_shape)).ravel() @@ -150,20 +149,20 @@ def halfsampler_for(shape): h = int(shape[0]) w = int(shape[1]) d = int(shape[2]) if len(shape) > 2 else 1 - + JS = np.arange(h*w*d).reshape((h,w,d)) JS = JS[::2,::2,:] JS = JS.flatten() - + IS = np.arange(len(JS)) data = np.ones(len(JS)) - + if len(shape) > 2: shape = (int(np.ceil(h/2.)), int(np.ceil(w/2.)), int(d)) else: shape = (int(np.ceil(h/2.)), int(np.ceil(w/2.))) return sp.csc_matrix((data, (IS, JS)), shape=(len(IS), h*w*d)), shape - + def filter_for_nopadding(shape, kernel): new_shape = np.array(shape).copy() @@ -190,7 +189,7 @@ def filter_for_nopadding(shape, kernel): JS.append(xs2.ravel() + ys2.ravel()*old_w) IS.append(np.arange(new_shape[0]*new_shape[1])) data.append(np.ones(IS[-1].size) * kernel[ky, kx]) - + IS = np.concatenate(IS) JS = np.concatenate(JS) @@ -205,19 +204,19 @@ def filter_for_nopadding(shape, kernel): IS = np.concatenate(IS) JS = np.concatenate(JS) data = np.concatenate(data) - + return sp.csc_matrix((data, (IS, JS))), new_shape def filter_for(h, w, d, kernel): - kernel = np.atleast_3d(kernel) + kernel = np.atleast_3d(kernel) if kernel.shape[2] != d: kernel = np.tile(kernel, (1, 1, d)) - + kxm = (kernel.shape[1]+1) / 2 kym = (kernel.shape[0]+1) / 2 - - + + xs = np.tile(np.arange(w), (int(h), 1)) ys = np.tile(np.arange(h), (int(w), 1)).T.copy() @@ -226,21 +225,21 @@ def filter_for(h, w, d, kernel): data = [] for ky in range(kernel.shape[0]): for kx in range(kernel.shape[1]): - for channel in range(d): + for channel in range(d): cky = ky - kym ckx = kx - kxm - + xs2 = np.clip(xs + ckx, 0, w-1) ys2 = np.clip(ys + cky, 0, h-1) - + IS.append(np.arange(w*h)*d+channel) JS.append((xs2.ravel() + ys2.ravel()*w)*d+channel) data.append(np.ones(IS[-1].size) * kernel[ky, kx, channel]) - + IS = np.concatenate(IS) JS = np.concatenate(JS) data = np.concatenate(data) - + #if d > 1: # IS = [IS*d+k for k in range(d)] # JS = [JS*d+k for k in range(d)] @@ -248,18 +247,18 @@ def filter_for(h, w, d, kernel): # IS = np.concatenate(IS) # JS = np.concatenate(JS) # data = np.concatenate(data) - # - + # + return sp.csc_matrix((data, (IS, JS)), shape=(h*w*d, h*w*d)) - - - + + + def main(): pass - + if __name__ == '__main__': main() diff --git a/opendr/geometry.py b/opendr/geometry.py index a30365c..8cd062f 100755 --- a/opendr/geometry.py +++ b/opendr/geometry.py @@ -38,7 +38,7 @@ def volume(v, f): volumes = (-v321 + v231 + v312 - v132 - v213 + v123) * (1./6.) return ch.abs(ch.sum(volumes)) - + class NormalizedNx3(Ch): dterms = 'v' @@ -95,7 +95,7 @@ class ndot(ch.Ch): def compute_r(self): return np.einsum('abc,acd->abd', self.mtx1.r, self.mtx2.r) - + def compute_d1(self): # To stay consistent with numpy, we must upgrade 1D arrays to 2D mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape)<2 else self.mtx1.r @@ -105,13 +105,13 @@ def compute_d1(self): return sp.kron(sp.eye(mtx1r.shape[0], mtx1r.shape[0]),mtx2r.T) else: mtx2f = mtx2r.reshape((-1, mtx2r.shape[-2], mtx2r.shape[-1])) - mtx2f = np.rollaxis(mtx2f, -1, -2) #transpose basically + mtx2f = np.rollaxis(mtx2f, -1, -2) #transpose basically result = sp.block_diag([np.kron(np.eye(mtx1r.shape[-2], mtx1r.shape[-2]),m2) for m2 in mtx2f]) assert(result.shape[0] == self.r.size) return result def compute_d2(self): - + # To stay consistent with numpy, we must upgrade 1D arrays to 2D mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape)<2 else self.mtx1.r mtx2r = col(self.mtx2.r) if len(self.mtx2.r.shape)<2 else self.mtx2.r @@ -121,12 +121,12 @@ def compute_d2(self): elif mtx2r.ndim <= 2: return sp.kron(mtx1r, sp.eye(mtx2r.shape[1],mtx2r.shape[1])) else: - mtx1f = mtx1r.reshape((-1, mtx1r.shape[-2], mtx1r.shape[-1])) + mtx1f = mtx1r.reshape((-1, mtx1r.shape[-2], mtx1r.shape[-1])) result = sp.block_diag([np.kron(m1, np.eye(mtx2r.shape[-1],mtx2r.shape[-1])) for m1 in mtx1f]) assert(result.shape[0] == self.r.size) return result - - + + def compute_dr_wrt(self, wrt): if wrt is self.mtx1 and wrt is self.mtx2: @@ -142,7 +142,7 @@ def face_bases(v, f): t2 = TriEdges(f, 2, 0, v).reshape((-1,3)) #t3 = NormalizedNx3(CrossProduct(t1, t2)).reshape((-1,3)) #t3 = CrossProduct(t1, t2).reshape((-1,3)) - + # Problem: cross-product is proportional in length to len(t1)*len(t2) # Solution: divide by sqrt(sqrt(len(cross-product))) t3 = CrossProduct(t1, t2).reshape((-1,3)); t3 = t3 / col(ch.sum(t3**2., axis=1)**.25) @@ -154,7 +154,7 @@ def edge_defs(v,f): fb = face_bases(v, f) fpe = get_faces_per_edge(v.r, f) return ndot(fb[fpe[:,0]], ch.linalg.inv(fb[fpe[:,1]])) - + def FirstEdgesMtx(v, f, want_big=True): cnct = get_vert_connectivity((v.r if hasattr(v, 'r') else v), f) @@ -162,25 +162,25 @@ def FirstEdgesMtx(v, f, want_big=True): JS = np.array(nbrs) IS = np.arange(len(JS)) data = np.ones(IS.size) - + if want_big: IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) data = np.concatenate((data, data, data)) - + return sp.csc_matrix((data, (IS, JS)), shape=(JS.size, JS.size)) - -def SecondFundamentalForm(v, f): + +def SecondFundamentalForm(v, f): from chumpy import hstack, vstack from chumpy.linalg import Pinv nbrs = MatVecMult(FirstEdgesMtx(v, f, want_big=True), v.ravel()).reshape((-1,3)) - + b0 = VertNormals(f=f, v=v) b1 = NormalizedNx3(CrossProduct(b0, nbrs-v)).reshape((-1,3)) b2 = NormalizedNx3(CrossProduct(b0, b1)).reshape((-1,3)) - + cnct = get_vert_connectivity(np.asarray(v), f) ffs = [] for i in range(v.size/3): @@ -195,8 +195,8 @@ def SecondFundamentalForm(v, f): ffs = vstack(ffs) return ffs - - + + def GaussianCurvature(v, f): ff = SecondFundamentalForm(v, f) result = ff[:,0] * ff[:,2] - ff[:,1]**2. @@ -205,18 +205,18 @@ def GaussianCurvature(v, f): class Rodrigues(Ch): dterms = 'rt' - + def compute_r(self): return cv2.Rodrigues(self.rt.r)[0] - + def compute_dr_wrt(self, wrt): if wrt is self.rt: return cv2.Rodrigues(self.rt.r)[1].T - - + + def TriArea(v_init, f, normalize): """ Returns a Ch object whose only attribute "v" represents the flattened vertices.""" - + if normalize: nm = lambda x : NormalizedNx3(x) else: @@ -238,12 +238,12 @@ def AcosTriAngles(v, f, normalize): Sum3xN(NormalizedNx3(TriEdges(f, 1, 0, nm(v))) * NormalizedNx3(TriEdges(f, 2, 0, nm(v)))) & Sum3xN(NormalizedNx3(TriEdges(f, 2, 1, nm(v))) * NormalizedNx3(TriEdges(f, 0, 1, nm(v)))) & Sum3xN(NormalizedNx3(TriEdges(f, 0, 2, nm(v))) * NormalizedNx3(TriEdges(f, 1, 2, nm(v))))) - + class VertNormals(Ch): """If normalized==True, normals are normalized; otherwise they'll be about as long as neighboring edges.""" - + dterms = 'v' terms = 'f', 'normalized' term_order = 'v', 'f', 'normalized' @@ -252,7 +252,7 @@ def on_changed(self, which): if not hasattr(self, 'normalized'): self.normalized = True - + if hasattr(self, 'v') and hasattr(self, 'f'): if 'f' not in which and hasattr(self, 'faces_by_vertex') and self.faces_by_vertex.shape[0]/3 == self.v.shape[0]: self.tns.v = self.v @@ -272,22 +272,22 @@ def on_changed(self, which): self.tns = Ch(lambda v : CrossProduct(TriEdges(f,1,0,v), TriEdges(f,2,0, v))) self.tns.v = self.v - + if self.normalized: tmp = MatVecMult(self.faces_by_vertex, self.tns) self.normals = NormalizedNx3(tmp) - else: + else: test = self.faces_by_vertex.dot(np.ones(self.faces_by_vertex.shape[1])) faces_by_vertex = sp.diags([1. / test], [0]).dot(self.faces_by_vertex).tocsc() normals = MatVecMult(faces_by_vertex, self.tns).reshape((-1,3)) normals = normals / (ch.sum(normals**2, axis=1) ** .25).reshape((-1,1)) self.normals = normals - - + + def compute_r(self): return self.normals.r.reshape((-1,3)) - + def compute_dr_wrt(self, wrt): if wrt is self.v: return self.normals.dr_wrt(wrt) @@ -314,7 +314,7 @@ def compute_r(self): def compute_dr_wrt(self, wrt): if wrt is not self.v: return None - + cplus = self.cplus cminus = self.cminus vplus = self.f[:,cplus] @@ -329,25 +329,25 @@ def compute_dr_wrt(self, wrt): def _edges_for(v, f, cplus, cminus): return ( - v.reshape(-1,3)[f[:,cplus],:] - + v.reshape(-1,3)[f[:,cplus],:] - v.reshape(-1,3)[f[:,cminus],:]).ravel() - + class CrossProduct(Ch): terms = [] dterms = 'a', 'b' - + def on_changed(self, which): if 'a' in which: a = self.a.r.reshape((-1,3)) self.a1 = a[:,0] self.a2 = a[:,1] self.a3 = a[:,2] - + if 'b' in which: - b = self.b.r.reshape((-1,3)) + b = self.b.r.reshape((-1,3)) self.b1 = b[:,0] self.b2 = b[:,1] - self.b3 = b[:,2] + self.b3 = b[:,2] def compute_r(self): @@ -358,7 +358,7 @@ def compute_r(self): def compute_dr_wrt(self, obj): if obj not in (self.a, self.b): return None - + sz = self.a.r.size if not hasattr(self, 'indices') or self.indices.size != sz*3: self.indptr = np.arange(0,(sz+1)*3,3) @@ -397,18 +397,18 @@ def Ax(self): """ # 0 -self.a3 self.a2 # self.a3 0 -self.a1 - # -self.a2 self.a1 0 + # -self.a2 self.a1 0 m = np.zeros((len(self.a1), 3, 3)) m[:, 0, 1] = -self.a3 m[:, 0, 2] = +self.a2 m[:, 1, 0] = +self.a3 m[:, 1, 2] = -self.a1 m[:, 2, 0] = -self.a2 - m[:, 2, 1] = +self.a1 + m[:, 2, 1] = +self.a1 return m @depends_on('b') - def Bx(self): + def Bx(self): """Compute a stack of skew-symmetric matrices which can be multiplied by 'a' to get the cross product. See: @@ -417,8 +417,8 @@ def Bx(self): # 0 self.b3 -self.b2 # -self.b3 0 self.b1 # self.b2 -self.b1 0 - - + + m = np.zeros((len(self.b1), 3, 3)) m[:, 0, 1] = +self.b3 m[:, 0, 2] = -self.b2 @@ -435,11 +435,11 @@ def _call_einsum_matvec(m, righthand): def _call_einsum_matmat(m, righthand): r = righthand.reshape(m.shape[0],3,-1) - return np.einsum('ijk,ikm->ijm', m, r).reshape(-1,r.shape[2]) + return np.einsum('ijk,ikm->ijm', m, r).reshape(-1,r.shape[2]) def main(): pass - + if __name__ == '__main__': main() diff --git a/opendr/lighting.py b/opendr/lighting.py index 055f9a9..4213a4b 100755 --- a/opendr/lighting.py +++ b/opendr/lighting.py @@ -37,7 +37,7 @@ def real_sh_coeff(xyz_samples): real_coeff[:,6] = (np.sqrt(5)/(2*d_sqrt_pi))*(3*xyz_samples[:,2]**2-1) real_coeff[:,7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,2] real_coeff[:,8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:,0]**2 - xyz_samples[:,1]**2) - return real_coeff + return real_coeff @@ -48,14 +48,14 @@ class SphericalHarmonics(Ch): d_sqrt_pi = 2*np.sqrt(np.pi) K = np.array([ 1./d_sqrt_pi, - np.sqrt(3)/d_sqrt_pi, - np.sqrt(3)/d_sqrt_pi, - np.sqrt(3)/d_sqrt_pi, - np.sqrt(15)/d_sqrt_pi, - np.sqrt(15)/d_sqrt_pi, + np.sqrt(3)/d_sqrt_pi, + np.sqrt(3)/d_sqrt_pi, + np.sqrt(3)/d_sqrt_pi, + np.sqrt(15)/d_sqrt_pi, + np.sqrt(15)/d_sqrt_pi, np.sqrt(5)/(2*d_sqrt_pi), - np.sqrt(15)/d_sqrt_pi, - np.sqrt(15)/(2*d_sqrt_pi)]) + np.sqrt(15)/d_sqrt_pi, + np.sqrt(15)/(2*d_sqrt_pi)]) @property def num_channels(self): @@ -64,13 +64,13 @@ def num_channels(self): def on_changed(self, which): if 'vn' in which: vn = self.vn.r.reshape((-1,3)) - + # Conversion from normals to spherical harmonics found in... # http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates self.theta = np.arccos(vn[:,2]) self.phi = np.arctan2(vn[:,1], vn[:,0]) - - self.sh_coeffs = real_sh_coeff(vn) + + self.sh_coeffs = real_sh_coeff(vn) self.num_verts = self.sh_coeffs.shape[0] if 'light_color' in which or self.mtx.shape[1] != self.num_verts: @@ -79,15 +79,15 @@ def on_changed(self, which): JS = np.repeat(np.arange(self.num_verts), nc) data = (row(self.light_color)*np.ones((self.num_verts, nc))).ravel() self.mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*nc, self.num_verts)) - - + + def compute_r(self): comps = self.components.r n = len(comps) result = self.mtx.dot(self.sh_coeffs[:,:n].dot(col(self.components.r))) result[result<0] = 0 return result.reshape((-1,self.num_channels)) - + def compute_dr_wrt(self, wrt): comps = np.zeros(9) comps[:len(self.components.r)] = self.components.r @@ -105,14 +105,14 @@ def compute_dr_wrt(self, wrt): #real_coeff[:,4] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,1] VS0 += vn[:,1] * comps[4] VS1 += vn[:,0] * comps[4] - + #real_coeff[:,5] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,1]*xyz_samples[:,2] VS1 += vn[:,2]*comps[5] VS2 += vn[:,1]*comps[5] - + #real_coeff[:,6] = (np.sqrt(5)/2*d_sqrt_pi)*(3*xyz_samples[:,2]**2-1) VS2 += 6*vn[:,2] * comps[6] - + #real_coeff[:,7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,2] VS0 += vn[:,2] * comps[7] VS2 += vn[:,0] * comps[7] @@ -120,26 +120,26 @@ def compute_dr_wrt(self, wrt): #real_coeff[:,8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:,0]**2 - xyz_samples[:,1]**2) VS0 += 2. * vn[:,0] * comps[8] VS1 -= 2. * vn[:,1] * comps[8] - + rng = np.arange(self.sh_coeffs.shape[0]) IS = np.concatenate((rng, rng, rng)) JS = np.concatenate((rng*3, rng*3+1, rng*3+2)) data = np.concatenate((VS0, VS1, VS2)) result = self.mtx.dot(sp.csc_matrix((data, (IS, JS)))) - + elif wrt is self.components: comps = self.components.r - n = len(comps) + n = len(comps) result = self.mtx.dot(self.sh_coeffs[:,:n]) else: return None - + which = np.nonzero(self.r.ravel()>0)[0] data = np.ones_like(which) gr_equal_zero = sp.csc_matrix((data, (which, which)), shape=(self.r.size, self.r.size)) return gr_equal_zero.dot(result) - + def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_t=None, camera_rt=None): """ @@ -182,7 +182,7 @@ def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_ class LambertianPointLight(Ch): terms = 'f', 'num_verts', 'light_color', 'double_sided' dterms = 'light_pos', 'v', 'vc', 'vn' - + def on_changed(self, which): if not hasattr(self, '_lpl'): if getattr(self, 'double_sided', False): @@ -192,14 +192,14 @@ def on_changed(self, which): else: self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) if not hasattr(self, 'ldn'): - self.ldn = LightDotNormal(self.v.r.size/3) + self.ldn = LightDotNormal(self.v.r.size/3) if not hasattr(self, 'vn'): logger.info('LambertianPointLight using auto-normals. This will be slow for derivative-free computations.') self.vn = VertNormals(f=self.f, v=self.v) self.vn.needs_autoupdate = True if 'v' in which and hasattr(self.vn, 'needs_autoupdate') and self.vn.needs_autoupdate: self.vn.v = self.v - + ldn_args = {k: getattr(self, k) for k in which if k in ('light_pos', 'v', 'vn')} if len(ldn_args) > 0: self.ldn.set(**ldn_args) @@ -219,10 +219,10 @@ def on_changed(self, which): @property def num_channels(self): return self.light_color.size - + def compute_r(self): return self._lpl.r - + def compute_dr_wrt(self, wrt): if wrt is self._lpl: return 1 diff --git a/opendr/renderer.py b/opendr/renderer.py index dff0c52..4171e6b 100755 --- a/opendr/renderer.py +++ b/opendr/renderer.py @@ -24,8 +24,8 @@ else: from contexts.ctx_mesa import OsContext -from chumpy import * -from contexts._constants import * +from chumpy import * # pylint: disable=wildcard-import, unused-wildcard-import +from contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import from chumpy.utils import row, col @@ -89,8 +89,8 @@ def fpe(self): class DepthRenderer(BaseRenderer): terms = 'f', 'frustum', 'background_image','overdraw', 'x0', 'x1', 'y0', 'y1' - dterms = 'camera', 'v' - + dterms = 'camera', 'v' + @property def shape(self): @@ -99,12 +99,12 @@ def shape(self): def compute_r(self): tmp = self.camera.r return self.depth_image.reshape((self.frustum['height'], self.frustum['width'])) - + def compute_dr_wrt(self, wrt): - + if wrt is not self.camera and wrt is not self.v: return None - + visibility = self.visibility_image visible = np.nonzero(visibility.ravel() != 4294967295)[0] barycentric = self.barycentric_image @@ -151,7 +151,7 @@ def compute_dr_wrt(self, wrt): result2 = sp.csc_matrix((data, (IS, JS)), shape=(self.frustum['height']*self.frustum['width'], self.v.r.size)) return result2 - + def on_changed(self, which): if 'frustum' in which: @@ -161,15 +161,15 @@ def on_changed(self, which): self.glf.Viewport(0, 0, w, h) self.glb = OsContext(w, h, typ=GL_UNSIGNED_BYTE) self.glb.Viewport(0, 0, w, h) - - + + if 'frustum' in which or 'camera' in which: setup_camera(self.glb, self.camera, self.frustum) setup_camera(self.glf, self.camera, self.frustum) if not hasattr(self, 'overdraw'): self.overdraw = True - + assert(self.v is self.camera.v) @@ -242,14 +242,14 @@ def getDepthMesh(self, depth_image=None): w = self.frustum['width'] h = self.frustum['height'] idxs = np.arange(w*h).reshape((h, w)) - + # v0 is upperleft, v1 is upper right, v2 is lowerleft, v3 is lowerright v0 = col(idxs[:-1,:-1]) v1 = col(idxs[:-1,1:]) v2 = col(idxs[1:,:-1]) v3 = col(idxs[1:,1:]) - f = np.hstack((v0, v1, v2, v1, v3, v2)).reshape((-1,3)) + f = np.hstack((v0, v1, v2, v1, v3, v2)).reshape((-1,3)) return v, f @@ -265,19 +265,19 @@ def shape(self): def compute_r(self): tmp = self.camera.r return self.color_image - + def compute_dr_wrt(self, wrt): if wrt is not self.camera: return None - + visibility = self.boundaryid_image - shape = visibility.shape - + shape = visibility.shape + visible = np.nonzero(visibility.ravel() != 4294967295)[0] num_visible = len(visible) barycentric = self.barycentric_image - + return common.dImage_wrt_2dVerts(self.color_image, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.vpe) def on_changed(self, which): @@ -288,14 +288,14 @@ def on_changed(self, which): self.glf.Viewport(0, 0, w, h) self.glb = OsContext(w, h, typ=GL_UNSIGNED_BYTE) self.glb.Viewport(0, 0, w, h) - + if 'frustum' in which or 'camera' in which: setup_camera(self.glb, self.camera, self.frustum) setup_camera(self.glf, self.camera, self.frustum) - + if not hasattr(self, 'overdraw'): self.overdraw = True - + @depends_on(terms+dterms) def color_image(self): self._call_on_changed() @@ -305,7 +305,7 @@ def color_image(self): class ColoredRenderer(BaseRenderer): terms = 'f', 'frustum', 'background_image', 'overdraw', 'num_channels' - dterms = 'vc', 'camera', 'bgcolor' + dterms = 'vc', 'camera', 'bgcolor' @property def shape(self): @@ -319,16 +319,16 @@ def shape(self): def compute_r(self): tmp = self.camera.r return self.color_image # .reshape((self.frustum['height'], self.frustum['width'], -1)).squeeze() - + def compute_dr_wrt(self, wrt): if wrt is not self.camera and wrt is not self.vc and wrt is not self.bgcolor: return None - + visibility = self.visibility_image shape = visibility.shape color = self.color_image - + visible = np.nonzero(visibility.ravel() != 4294967295)[0] num_visible = len(visible) @@ -355,11 +355,11 @@ def on_changed(self, which): self.glf.Viewport(0, 0, w, h) self.glb = OsContext(w, h, typ=GL_UNSIGNED_BYTE) self.glb.Viewport(0, 0, w, h) - + if 'frustum' in which or 'camera' in which: setup_camera(self.glb, self.camera, self.frustum) setup_camera(self.glf, self.camera, self.frustum) - + if not hasattr(self, 'num_channels'): self.num_channels = 3 @@ -369,7 +369,7 @@ def on_changed(self, which): if not hasattr(self, 'overdraw'): self.overdraw = True - + if 'bgcolor' in which or ('frustum' in which and hasattr(self, 'bgcolor')): self.glf.ClearColor(self.bgcolor.r[0], self.bgcolor.r[1%self.num_channels], self.bgcolor.r[2%self.num_channels], 1.) @@ -382,7 +382,7 @@ def filter_for_triangles(self, which_triangles): vim = self.visibility_image+1 arr = np.zeros(len(self.f)+1) arr[which_triangles+1] = 1 - + relevant_pixels = arr[vim.ravel()] cim2 = cim.copy() * np.atleast_3d(relevant_pixels.reshape(vim.shape)) relevant_pixels = np.nonzero(arr[vim.ravel()])[0] @@ -444,7 +444,7 @@ def boundarycolor_image(self): gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_colored_primitives(gl, self.v.r.reshape((-1,3)), self.vpe, colors) return np.asarray(deepcopy(gl.getImage()), np.float64) - + class TexturedRenderer(ColoredRenderer): terms = 'f', 'frustum', 'vt', 'ft', 'background_image', 'overdraw' @@ -460,7 +460,7 @@ def shape(self): @property def num_channels(self): return 3 - + def release_textures(self): if hasattr(self, 'textureID'): arr = np.asarray(np.array([self.textureID]), np.uint32) @@ -469,7 +469,7 @@ def release_textures(self): def compute_dr_wrt(self, wrt): result = super(TexturedRenderer, self).compute_dr_wrt(wrt) - + if wrt is self.vc: cim = self.draw_color_image(with_vertex_colors=False).ravel() cim = sp.spdiags(row(cim), [0], cim.size, cim.size) @@ -496,7 +496,7 @@ def compute_dr_wrt(self, wrt): return sp.csc_matrix((data, (IS, JS)), shape=(self.r.size, wrt.r.size)) - + return result def on_changed(self, which): @@ -507,7 +507,7 @@ def on_changed(self, which): gl = self.glf texture_data = np.array(self.texture_image*255., dtype='uint8', order='C') tmp = np.zeros(2, dtype=np.uint32) - + self.release_textures() gl.GenTextures(1, tmp) # TODO: free after done self.textureID = tmp[0] @@ -525,7 +525,7 @@ def mesh_tex_coords(self): data = np.asarray(self.vt[ftidxs].astype(np.float32)[:,0:2], np.float32, order='C') data[:,1] = 1.0 - 1.0*data[:,1] return data - + # Depends on 'f' because vpe/fpe depend on f @depends_on('vt', 'ft', 'f') def wireframe_tex_coords(self): @@ -534,7 +534,7 @@ def wireframe_tex_coords(self): edata = np.zeros((self.vpe.size,2), dtype=np.float32, order='C') edata = vvt[self.vpe.ravel()] return edata - + def texture_mapping_on(self, gl, with_vertex_colors): gl.Enable(GL_TEXTURE_2D) gl.TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) @@ -546,7 +546,7 @@ def texture_mapping_on(self, gl, with_vertex_colors): def texture_mapping_off(self, gl): gl.Disable(GL_TEXTURE_2D) gl.DisableClientState(GL_TEXTURE_COORD_ARRAY) - + # TODO: can this not be inherited from base? turning off texture mapping in that instead? @depends_on(dterms+terms) @@ -639,15 +639,15 @@ def draw_edge_visibility(gl, v, e, f, hidden_wireframe=True): ec[:, 1] = (ec[:, 1] >> 8 ) & 255 ec[:, 2] = (ec[:, 2] >> 16 ) & 255 ec = np.asarray(ec, dtype=np.uint8) - + draw_colored_primitives(gl, v, e, ec) - + if hidden_wireframe: gl.Enable(GL_POLYGON_OFFSET_FILL) gl.PolygonOffset(10.0, 1.0) draw_colored_primitives(gl, v, f, fc=np.zeros(f.shape)) gl.Disable(GL_POLYGON_OFFSET_FILL) - + raw = np.asarray(gl.getImage(), np.uint32) raw = raw[:,:,0] + raw[:,:,1]*256 + raw[:,:,2]*256*256 - 1 return raw @@ -702,7 +702,7 @@ def draw_boundaryid_image(gl, v, f, vpe, fpe, camera, x0=None, x1=None, y0=None, if False: visibility = draw_edge_visibility(gl, v, vpe, f, hidden_wireframe=True) return visibility - + if True: #try: gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -721,7 +721,7 @@ def draw_boundaryid_image(gl, v, f, vpe, fpe, camera, x0=None, x1=None, y0=None, visibility[y1:] = -1 visibility[y0:y1, :x0] = -1 visibility[y0:y1, x1:] = -1 - + shape = visibility.shape visibility = visibility.ravel() visible = np.nonzero(visibility.ravel() != 4294967295)[0] @@ -743,8 +743,8 @@ def setup_camera(gl, camera, frustum): frustum['near'], frustum['far'], camera.view_matrix, camera.k.r) - - + + vs_source = """ #version 120 @@ -830,7 +830,7 @@ def _setup_camera(gl, cx, cy, fx, fy, w, h, near, far, view_matrix, k): k = np.asarray(k) gl.MatrixMode(GL_PROJECTION) gl.LoadIdentity(); - + f = 0.5 * (fx + fy) right = (w-(cx+pixel_center_offset)) * (near/f) left = -(cx+pixel_center_offset) * (near/f) diff --git a/opendr/rogrenderer.py b/opendr/rogrenderer.py index b4d96c8..b8ab683 100644 --- a/opendr/rogrenderer.py +++ b/opendr/rogrenderer.py @@ -20,28 +20,28 @@ class RogTexRenderer(TexturedRenderer): def draw_color_image(self, with_vertex_colors): result = super(self.__class__, self).draw_color_image(with_vertex_colors) return self.compute_rog(result) - + def compute_rog(self, im, is_real=False): - if (self.sigma_small>=self.sigma_big) or (self.sigma_small==0): return im + if (self.sigma_small>=self.sigma_big) or (self.sigma_small==0): return im if self.frustum['height'] != np.shape(im)[0]: im = cv2.resize(im, (self.frustum['width'], self.frustum['height'] )) if (len(im.shape)==3): im = np.mean(im, axis=2) - im = np.asarray(im, np.float64)/255. + im = np.asarray(im, np.float64)/255. visibility = super(self.__class__, self).visibility_image im[visibility == 4294967295] = np.nan - + ksize = self.sigma_small*4 if ksize % 2 == 0: ksize += 1 smblur = cv2.GaussianBlur(im, (ksize, ksize), self.sigma_small) - + ksize = self.sigma_big*4 if ksize % 2 == 0: ksize += 1 bgblur = cv2.GaussianBlur(im, (ksize, ksize), self.sigma_big) - + # FIXME? zero values - im = smblur / bgblur - + im = smblur / bgblur + if is_real: self.bckground_mask = np.ones_like(im); self.bckground_mask[np.isnan(im)] = np.nan @@ -51,30 +51,30 @@ def compute_rog(self, im, is_real=False): return im - + """def load_basics(): np.random.seed(0) - camera = get_camera(scaling=.4) + camera = get_camera(scaling=.4) camera, frustum = convertCam(camera) mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) - + lighting = LambertianPointLight( - f=mesh.f, - num_verts=len(mesh.v), - light_pos=np.array([-1000,-1000,-1000]), - vc=mesh.vc, + f=mesh.f, + num_verts=len(mesh.v), + light_pos=np.array([-1000,-1000,-1000]), + vc=mesh.vc, light_color=np.array([1., 1., 1.])) - + bgcolor = np.array([0.,0.,0.]) renderers = [ TexturedRenderer(f=mesh.f, vc=mesh.vc, v=mesh.v, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor), RogTexRenderer(f=mesh.f, vc=mesh.vc, v=mesh.v, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor, sigma_small=3, sigma_big=5)] - + return mesh, lighting, camera, frustum, renderers """ - + if __name__ == '__main__': - + import matplotlib.pyplot as plt mesh, lighting, camera, frustum, renderers = load_basics() @@ -85,7 +85,7 @@ def compute_rog(self, im, is_real=False): plt.imshow(renderers[0].r) # Show ROG textured renderer - plt.figure() + plt.figure() r2 = renderers[1].r.copy() r2 -= np.min(r2.ravel()) r2 /= np.max(r2.ravel()) diff --git a/opendr/simple.py b/opendr/simple.py index 3fee5e1..12ef192 100644 --- a/opendr/simple.py +++ b/opendr/simple.py @@ -1,38 +1,36 @@ __all__ = [] import camera -from camera import * +from camera import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += camera.__all__ import renderer -from renderer import * +from renderer import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += renderer.__all__ import lighting -from lighting import * +from lighting import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += lighting.__all__ import topology -from topology import * +from topology import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += topology.__all__ import geometry -from geometry import * +from geometry import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += geometry.__all__ import serialization -from serialization import * +from serialization import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += serialization.__all__ import utils -from utils import * +from utils import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += utils.__all__ import filters -from filters import * +from filters import * # pylint: disable=wildcard-import, unused-wildcard-import __all__ += filters.__all__ import chumpy as ch __all__ += ['ch'] - - diff --git a/opendr/slider_demo.py b/opendr/slider_demo.py index 2498512..72a61b1 100644 --- a/opendr/slider_demo.py +++ b/opendr/slider_demo.py @@ -5,11 +5,11 @@ def nothing(x): pass - - + + def get_renderer(): import chumpy as ch - from opendr.everything import * + from opendr.everything import * # pylint: disable=unused-wildcard-import, unused-variable # Load mesh m = load_mesh('/Users/matt/geist/OpenDR/test_dr/nasa_earth.obj') @@ -25,8 +25,8 @@ def get_renderer(): rn.vc = SphericalHarmonics(vn=VertNormals(v=rn.v, f=rn.f), components=ch.array([4.,0.,0.,0.]), light_color=ch.ones(3)) return rn - - + + def main(): # Create a black image, a window img = np.zeros((300,512,3), np.uint8) @@ -57,7 +57,7 @@ def main(): k = cv2.waitKey(1) & 0xFF if k == 27: break - + for k, v in tracked.items(): v[:] = np.array(cv2.getTrackbarPos(k, 'image')).astype(np.float32)*4/cnst if tracked[k].r[0] != old_tracked[k].r[0]: @@ -68,10 +68,10 @@ def main(): # drim = drim - np.min(drim) # drim = drim / np.max(drim) cv2.imshow('derivatives', drim) - + cv2.waitKey(1) old_tracked = deepcopy(tracked) - # while True: + # while True: # for k_change in sorted(tracked.keys()): # if k_change == 'sph0': # continue @@ -81,7 +81,7 @@ def main(): # k = cv2.waitKey(1) & 0xFF # if k == 27: # break - # + # # for k, v in tracked.items(): # v[:] = np.array(cv2.getTrackbarPos(k, 'image')).astype(np.float32)*4/cnst # if tracked[k].r[0] != old_tracked[k].r[0]: @@ -92,10 +92,10 @@ def main(): # # drim = drim - np.min(drim) # # drim = drim / np.max(drim) # cv2.imshow('derivatives', drim) - # - # + # + # # print rn.vc.components - # + # # cv2.waitKey(1) # old_tracked = deepcopy(tracked) diff --git a/opendr/test_camera.py b/opendr/test_camera.py index ab7952a..b5f8ac8 100755 --- a/opendr/test_camera.py +++ b/opendr/test_camera.py @@ -16,12 +16,12 @@ class TestCamera(unittest.TestCase): - + def get_cam_params(self): v_raw = np.sin(np.arange(900)).reshape((-1,3)) v_raw[:, 2] -= 2 - + rt = ch.zeros(3) t = ch.zeros(3) f = ch.array([500,500]) @@ -30,33 +30,33 @@ def get_cam_params(self): cam_params = {'v': ch.Ch(v_raw), 'rt': rt, 't': t, 'f': f, 'c': c, 'k': k} return cam_params - + def test_project_points_without_derivatives(self): from util_tests import get_earthmesh cam_params = self.get_cam_params() mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) - + pp = ProjectPoints(f=cam_params['f'], rt=cam_params['rt'], t=cam_params['t'], k=cam_params['k'], c=cam_params['c']) pp.v = mesh.v np.testing.assert_array_almost_equal(pp.r, pp.r_and_derivatives[0].squeeze()) - + def test_project_points(self): self.project_points(ProjectPoints) def test_project_points_3d(self): self.project_points(ProjectPoints3D) - + def project_points(self, cls): cam_params = self.get_cam_params() for key, value in cam_params.items(): - + eps = (np.random.random(value.r.size)-.5) * 1e-5 pp_dist = cls(**cam_params) - - old_val = pp_dist.r.copy() + + old_val = pp_dist.r.copy() old_dr = pp_dist.dr_wrt(value).dot(eps) - + tmp = cam_params[key].r.copy() tmp += eps.reshape(tmp.shape) @@ -66,7 +66,7 @@ def project_points(self, cls): raw_dr_diff = np.abs(old_dr.flatten() - diff.flatten()) med_diff = np.median(raw_dr_diff) max_diff = np.max(raw_dr_diff) - + #pct_diff = (100. * max_diff / np.mean(np.abs(old_val.flatten()))) # print 'testing for %s' % (key,) # print 'empirical' + str(diff.flatten()[:5]) @@ -77,10 +77,10 @@ def project_points(self, cls): self.assertLess(med_diff, 1e-8) self.assertLess(max_diff, 5e-8) - + pp_dist = cls(**cam_params) - + # Test to make sure that depends_on is working for name in ('rt', 't', 'f', 'c', 'k'): aa = pp_dist.camera_mtx diff --git a/opendr/test_depth_renderer.py b/opendr/test_depth_renderer.py index 080bbb6..ee02e7c 100644 --- a/opendr/test_depth_renderer.py +++ b/opendr/test_depth_renderer.py @@ -26,7 +26,7 @@ def test_depth_image(self): rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3)) - + # import time # tm = time.time() # rn.r diff --git a/opendr/test_geometry.py b/opendr/test_geometry.py index 0a524c5..a95c10d 100755 --- a/opendr/test_geometry.py +++ b/opendr/test_geometry.py @@ -25,12 +25,12 @@ def test_rodrigues(self): rt2 = rt + np.random.rand(3)*1e-5 foo1 = Rodrigues(rt = rt) foo2 = Rodrigues(rt = rt2) - + empirical = (foo2.r - foo1.r).flatten() predicted = foo1.dr_wrt(foo1.rt).dot(rt2-rt) - + self.assertTrue(np.max(np.abs(empirical - predicted)) < 1e-10) - + def test_vert_normals(self): from geometry import VertNormals @@ -46,8 +46,8 @@ def test_vert_normals(self): v += eps vn2 = VertNormals(v=v, f=f) empirical_diff = (vn2.r - vn1.r).reshape((-1,3)) - - predicted_diff = dr_predicted.dot(eps.flatten()).reshape((-1,3)) + + predicted_diff = dr_predicted.dot(eps.flatten()).reshape((-1,3)) if False: print np.max(np.abs(empirical_diff-predicted_diff)) diff --git a/opendr/test_renderer.py b/opendr/test_renderer.py index 8360bbe..b8629e6 100755 --- a/opendr/test_renderer.py +++ b/opendr/test_renderer.py @@ -17,7 +17,7 @@ except: from dummy import dummy as plt -from renderer import * +from renderer import * # pylint: disable=wildcard-import, unused-wildcard-import from chumpy import Ch from chumpy.utils import row, col from lighting import * @@ -25,9 +25,9 @@ from collections import OrderedDict - + visualize = False - + def getcam(): from camera import ProjectPoints @@ -58,7 +58,7 @@ def load_basics(self): np.random.seed(0) camera, frustum = getcam() mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) - + lighting_3channel = LambertianPointLight( f=mesh.f, num_verts=len(mesh.v), @@ -80,7 +80,7 @@ def load_basics(self): lightings = {1: lighting_1channel, 3: lighting_3channel} return mesh, lightings, camera, frustum, renderers - + def test_pyramids(self): """ Test that pyramid construction doesn't crash. No quality testing here. """ mesh, lightings, camera, frustum, renderers = self.load_basics() @@ -103,7 +103,7 @@ def test_pyramids(self): tm = time.time() _ = r.dr_wrt(rn) #print "trial %d: %.2fS " % (ii, time.time() - tm) - + def test_distortion(self): mesh, lightings, camera, frustum, renderers = self.load_basics() @@ -199,7 +199,7 @@ def test_cam_derivatives(self): lighting = lightings[renderer.num_channels] # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) mesh_verts = Ch(mesh.v.flatten()) camera.v = mesh_verts lighting.v = mesh_verts @@ -271,7 +271,7 @@ def test_cam_derivatives(self): self.assertLess(meanerror, info['meannz']) self.assertLess(mederror, info['mednz']) - + def test_vert_derivatives(self): mesh, lightings, camera, frustum, renderers = self.load_basics() @@ -282,8 +282,8 @@ def test_vert_derivatives(self): im_shape = renderer.shape # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) - mesh_verts = Ch(mesh.v.flatten()) + mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh_verts = Ch(mesh.v.flatten()) camera.set(v=mesh_verts) lighting.set(v=mesh_verts) renderer.set(camera=camera) @@ -292,7 +292,7 @@ def test_vert_derivatives(self): # Get pixels and derivatives r = renderer.r dr = renderer.dr_wrt(mesh_verts) - + # Establish a random direction direction = (np.random.rand(mesh.v.size).reshape(mesh.v.shape)-.5)*.1 + np.sin(mesh.v*10)*.2 direction *= .5 @@ -303,7 +303,7 @@ def test_vert_derivatives(self): lighting.set(v=mesh_verts) renderer.set(v=mesh_verts, vc=lighting) rfwd = renderer.r - + # Render going backward in that direction mesh_verts = Ch(mesh.v-direction*eps/2.) lighting.set(v=mesh_verts) @@ -312,7 +312,7 @@ def test_vert_derivatives(self): # Establish empirical and predicted derivatives dr_empirical = (np.asarray(rfwd, np.float64) - np.asarray(rbwd, np.float64)).ravel() / eps - dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) + dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) images = OrderedDict() images['shifted verts'] = np.asarray(rfwd, np.float64)-.5 @@ -330,7 +330,7 @@ def test_vert_derivatives(self): im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) - + print 'verts: median nonzero %.2e' % (np.median(np.abs(nonzero)),) print 'verts: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) plt.draw() @@ -338,12 +338,12 @@ def test_vert_derivatives(self): self.assertLess(np.mean(np.abs(nonzero)), 7e-2) self.assertLess(np.median(np.abs(nonzero)), 4e-2) - + def test_lightpos_derivatives(self): - + mesh, lightings, camera, frustum, renderers = self.load_basics() - + for renderer in renderers: @@ -351,7 +351,7 @@ def test_lightpos_derivatives(self): lighting = lightings[renderer.num_channels] # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) mesh_verts = Ch(mesh.v.flatten()) camera.set(v=mesh_verts) @@ -360,23 +360,23 @@ def test_lightpos_derivatives(self): light1_pos = Ch(np.array([-1000,-1000,-1000])) lighting.set(light_pos=light1_pos, v=mesh_verts) renderer.set(vc=lighting, v=mesh_verts) - - dr = renderer.dr_wrt(light1_pos).copy() + + dr = renderer.dr_wrt(light1_pos).copy() # Establish a random direction for the light direction = (np.random.rand(3)-.5)*1000. eps = 1. - + # Find empirical forward derivatives in that direction lighting.set(light_pos = light1_pos.r + direction*eps/2.) renderer.set(vc=lighting) rfwd = renderer.r - + # Find empirical backward derivatives in that direction lighting.set(light_pos = light1_pos.r - direction*eps/2.) renderer.set(vc=lighting) rbwd = renderer.r - + # Establish empirical and predicted derivatives dr_empirical = (np.asarray(rfwd, np.float64) - np.asarray(rbwd, np.float64)).ravel() / eps dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) @@ -397,30 +397,30 @@ def test_lightpos_derivatives(self): im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) - + plt.show() print 'lightpos: median nonzero %.2e' % (np.median(np.abs(nonzero)),) print 'lightpos: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) self.assertLess(np.mean(np.abs(nonzero)), 2.4e-2) self.assertLess(np.median(np.abs(nonzero)), 1.2e-2) - - - + + + def test_color_derivatives(self): - + mesh, lightings, camera, frustum, renderers = self.load_basics() - + for renderer in renderers: im_shape = renderer.shape lighting = lightings[renderer.num_channels] # Get pixels and dI/dC - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) mesh_verts = Ch(mesh.v) mesh_colors = Ch(mesh.vc) - camera.set(v=mesh_verts) + camera.set(v=mesh_verts) # import pdb; pdb.set_trace() # print '-------------------------------------------' @@ -469,20 +469,20 @@ def test_color_derivatives(self): im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) - + plt.show() print 'color: median nonzero %.2e' % (np.median(np.abs(nonzero)),) print 'color: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) self.assertLess(np.mean(np.abs(nonzero)), 2e-2) self.assertLess(np.median(np.abs(nonzero)), 4.5e-3) - + def plt_imshow(im): - #im = process(im, vmin, vmax) + #im = process(im, vmin, vmax) result = plt.imshow(im) plt.axis('off') - plt.subplots_adjust(bottom=0.01, top=.99, left=0.01, right=.99) + plt.subplots_adjust(bottom=0.01, top=.99, left=0.01, right=.99) return result diff --git a/opendr/test_sh.py b/opendr/test_sh.py index 16dbb37..5926ded 100755 --- a/opendr/test_sh.py +++ b/opendr/test_sh.py @@ -6,16 +6,16 @@ See LICENCE.txt for licensing and contact information. """ -from chumpy import Ch +import unittest import numpy as np +from chumpy import Ch from chumpy.utils import row, col -from lighting import SphericalHarmonics -import unittest +from opendr.lighting import SphericalHarmonics try: import matplotlib.pyplot as plt -except: - from dummy import dummy as plt -from topology import loop_subdivider +except ImportError: + from opendr.dummy import dummy as plt +from opendr.topology import loop_subdivider visualize = False @@ -25,7 +25,7 @@ def getcam(): w = 640 h = 320 - f = np.array([500,500]) + f = np.array([500, 500]) rt = np.zeros(3) t = np.zeros(3) k = np.zeros(5) @@ -46,7 +46,7 @@ def test_spherical_harmonics(self): global visualize if visualize: plt.ion() - + # Get mesh v, f = get_sphere_mesh() @@ -56,59 +56,59 @@ def test_spherical_harmonics(self): # Get camera cam, frustum = getcam() - + # Get renderer from renderer import ColoredRenderer cam.v = v 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])) - + + 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]): - + 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) - + 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.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[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) - + 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.subplot(1, 2, 1) plt.imshow(pred) - plt.title('pred (comp %d)' % (comp_idx,)) - plt.subplot(1,2,2) - + 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: @@ -117,7 +117,7 @@ def test_spherical_harmonics(self): 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])) @@ -127,7 +127,7 @@ def test_spherical_harmonics(self): self.assertTrue(med_diff / med_obs < .3) if visualize: plt.axis('off') - + def get_sphere_mesh(): from util_tests import get_earthmesh @@ -137,9 +137,9 @@ def get_sphere_mesh(): for i in range(3): mtx, f = loop_subdivider(v, f) - v = mtx.dot(v.ravel()).reshape((-1,3)) + v = mtx.dot(v.ravel()).reshape((-1, 3)) v /= 200. - v[:,2] += 2 + v[:, 2] += 2 return v, f @@ -154,4 +154,3 @@ def get_sphere_mesh(): unittest.TextTestRunner(verbosity=2).run(suite) plt.show() # import pdb; pdb.set_trace() - diff --git a/opendr/topology.py b/opendr/topology.py index fa52d96..f5c1993 100644 --- a/opendr/topology.py +++ b/opendr/topology.py @@ -8,10 +8,8 @@ __all__ = ['get_vertices_per_edge', 'get_faces_per_edge', 'get_vert_connectivity'] -import zlib import numpy as np import scipy.sparse as sp -import cPickle as pickle from chumpy.utils import row, col @@ -21,12 +19,12 @@ def get_vert_connectivity(mesh_v, mesh_f): nonzero element in position (15,12), that means vertex 15 is connected by an edge to vertex 12.""" - vpv = sp.csc_matrix((len(mesh_v),len(mesh_v))) + vpv = sp.csc_matrix((len(mesh_v), len(mesh_v))) # for each column in the faces... for i in range(3): - IS = mesh_f[:,i] - JS = mesh_f[:,(i+1)%3] + IS = mesh_f[:, i] + JS = mesh_f[:, (i+1)%3] data = np.ones(len(IS)) ij = np.vstack((row(IS.flatten()), row(JS.flatten()))) mtx = sp.csc_matrix((data, ij), shape=vpv.shape) @@ -43,7 +41,7 @@ def get_vertices_per_edge(mesh_v, mesh_f): vc = sp.coo_matrix(get_vert_connectivity(mesh_v, mesh_f)) result = np.hstack((col(vc.row), col(vc.col))) - result = result[result[:,0] < result[:,1]] # for uniqueness + result = result[result[:, 0] < result[:, 1]] # for uniqueness return result @@ -64,7 +62,7 @@ def get_faces_per_edge(mesh_v, mesh_f, verts_per_edge=None): faces = v2f[edge[0]].intersection(v2f[edge[1]]) faces = list(faces)[:2] for i, f in enumerate(faces): - fpe[idx,i] = f + fpe[idx, i] = f return fpe @@ -80,58 +78,56 @@ def loop_subdivider(mesh_v, mesh_f): ve = get_vertices_per_edge(mesh_v, mesh_f) vo = get_vert_opposites_per_edge(mesh_v, mesh_f) - if True: - # New values for each vertex - for idx in xrange(len(mesh_v)): + # New values for each vertex + for idx in xrange(len(mesh_v)): - # find neighboring vertices - nbrs = np.nonzero(vc[:,idx])[0] + # find neighboring vertices + nbrs = np.nonzero(vc[:, idx])[0] - nn = len(nbrs) + nn = len(nbrs) - if nn < 3: - wt = 0. - elif nn == 3: - wt = 3./16. - elif nn > 3: - wt = 3. / (8. * nn) - else: - raise Exception('nn should be 3 or more') - if wt > 0.: - for nbr in nbrs: - IS.append(idx) - JS.append(nbr) - data.append(wt) + if nn < 3: + wt = 0. + elif nn == 3: + wt = 3./16. + elif nn > 3: + wt = 3. / (8. * nn) + else: + raise Exception('nn should be 3 or more') + if wt > 0.: + for nbr in nbrs: + IS.append(idx) + JS.append(nbr) + data.append(wt) - JS.append(idx) - IS.append(idx) - data.append(1. - (wt * nn)) + JS.append(idx) + IS.append(idx) + data.append(1. - (wt * nn)) start = len(mesh_v) edge_to_midpoint = {} - if True: - # New values for each edge: - # new edge verts depend on the verts they span - for idx, vs in enumerate(ve): - - vsl = list(vs) - vsl.sort() - IS.append(start + idx) + # New values for each edge: + # new edge verts depend on the verts they span + for idx, vs in enumerate(ve): + + vsl = list(vs) + vsl.sort() + IS.append(start + idx) + IS.append(start + idx) + JS.append(vsl[0]) + JS.append(vsl[1]) + data.append(3./8) + data.append(3./8) + + opposites = vo[(vsl[0], vsl[1])] + for opp in opposites: IS.append(start + idx) - JS.append(vsl[0]) - JS.append(vsl[1]) - data.append(3./8) - data.append(3./8) + JS.append(opp) + data.append(2./8./len(opposites)) - opposites = vo[(vsl[0], vsl[1])] - for opp in opposites: - IS.append(start + idx) - JS.append(opp) - data.append(2./8./len(opposites)) - - edge_to_midpoint[(vsl[0], vsl[1])] = start + idx - edge_to_midpoint[(vsl[1], vsl[0])] = start + idx + edge_to_midpoint[(vsl[0], vsl[1])] = start + idx + edge_to_midpoint[(vsl[1], vsl[0])] = start + idx f = [] @@ -142,22 +138,22 @@ def loop_subdivider(mesh_v, mesh_f): v0 = edge_to_midpoint[(ff[i], ff[i+1])] v1 = ff[i+1] v2 = edge_to_midpoint[(ff[i+1], ff[i+2])] - f.append(row(np.array([v0,v1,v2]))) + f.append(row(np.array([v0, v1, v2]))) v0 = edge_to_midpoint[(ff[0], ff[1])] v1 = edge_to_midpoint[(ff[1], ff[2])] v2 = edge_to_midpoint[(ff[2], ff[3])] - f.append(row(np.array([v0,v1,v2]))) + f.append(row(np.array([v0, v1, v2]))) f = np.vstack(f) IS = np.array(IS, dtype=np.uint32) JS = np.array(JS, dtype=np.uint32) - if True: # for x,y,z coords - IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) - JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) - data = np.concatenate ((data,data,data)) + # for x,y,z coords + IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) + JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) + data = np.concatenate ((data, data, data)) ij = np.vstack((IS.flatten(), JS.flatten())) mtx = sp.csc_matrix((data, ij)) @@ -183,5 +179,3 @@ def get_vert_opposites_per_edge(mesh_v, mesh_f): else: result[key] = [val] return result - - diff --git a/opendr/util_tests.py b/opendr/util_tests.py index d10b6ad..0ed3354 100644 --- a/opendr/util_tests.py +++ b/opendr/util_tests.py @@ -3,15 +3,12 @@ from copy import deepcopy from os.path import join, split, exists import numpy as np -from cvwrap import cv2 - -from chumpy.utils import row, col -from utils import wget +from chumpy.utils import row +from opendr.cvwrap import cv2 +from opendr.utils import wget def get_earthmesh(trans, rotation): - from serialization import load_mesh - - from copy import deepcopy + from opendr.serialization import load_mesh if not hasattr(get_earthmesh, 'm'): def wg(url): @@ -42,8 +39,8 @@ def wg(url): def process(im, vmin, vmax): shape = im.shape im = deepcopy(im).flatten() - im[im>vmax] = vmax - im[im vmax] = vmax + im[im < vmin] = vmin im -= vmin im /= (vmax-vmin) im = im.reshape(shape) From 9be7c09a28c552fb23f6cbbc06b7f2f8db07320a Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Wed, 10 May 2017 17:35:50 -0400 Subject: [PATCH 52/56] fix more lint --- opendr/__init__.py | 166 +++++++-------- opendr/camera.py | 36 ++-- opendr/common.py | 12 +- opendr/cvwrap.py | 2 +- opendr/filters.py | 8 +- opendr/geometry.py | 210 ++++++++++--------- opendr/lighting.py | 138 ++++++------- opendr/renderer.py | 371 ++++++++++++++++------------------ opendr/rogrenderer.py | 12 +- opendr/serialization.py | 8 +- opendr/slider_demo.py | 18 +- opendr/test_camera.py | 20 +- opendr/test_depth_renderer.py | 34 ++-- opendr/test_geometry.py | 37 ++-- opendr/test_renderer.py | 171 ++++++++-------- opendr/test_sh.py | 96 +++++---- opendr/topology.py | 18 +- opendr/utils.py | 2 +- 18 files changed, 645 insertions(+), 714 deletions(-) diff --git a/opendr/__init__.py b/opendr/__init__.py index c41f8c6..b028a1b 100644 --- a/opendr/__init__.py +++ b/opendr/__init__.py @@ -18,10 +18,10 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc, texture_image=m.texture_image, ft=m.ft, vt=m.vt) @@ -36,23 +36,23 @@ def test(): demos['moments'] = """ from opendr.util_tests import get_earthmesh -from opendr.simple import * +from opendr.simple import * import numpy as np w, h = 320, 240 -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), 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.,1.,0.,0.,0.,0.,0.,0.,0.], +A = SphericalHarmonics(vn=VertNormals(v=V, f=m.f), + components=[3., 1., 0., 0., 0., 0., 0., 0., 0.], light_color=ch.ones(3)) -U = ProjectPoints(v=V, f=[300,300.], c=[w/2.,h/2.], k=ch.zeros(5), +U = ProjectPoints(v=V, f=[300, 300.], c=[w/2., h/2.], k=ch.zeros(5), t=ch.zeros(3), rt=ch.zeros(3)) -rn = TexturedRenderer(vc=A, camera=U, f=m.f, bgcolor=[0.,0.,0.], +rn = 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}) + frustum={'width':w, 'height':h, 'near':1, 'far':20}) i, j = ch.array([2.]), ch.array([1.]) xs, ys = ch.meshgrid(range(rn.shape[1]), range(rn.shape[0])) @@ -62,7 +62,7 @@ def test(): moment = ch.sum((rn_bw * ysp * xsp).ravel()) # Print our numerical result -print moment +print moment # Note that opencv produces the same result for 'm21', # and that other moments can be created by changing "i" and "j" above @@ -84,16 +84,16 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) -# THESE ARE THE 3 CRITICAL LINES +# THESE ARE THE 3 CRITICAL LINES m.v = m.v[m.f.ravel()] m.vc = m.vc[m.f.ravel()] -m.f = np.arange(m.f.size).reshape((-1,3)) +m.f = np.arange(m.f.size).reshape((-1, 3)) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) @@ -102,7 +102,7 @@ def test(): f=m.f, v=rn.v, num_verts=len(m.v), - light_pos=ch.array([-1000,-1000,-1000]), + light_pos=ch.array([-1000, -1000, -1000]), vc=m.vc, light_color=ch.array([1., 1., 1.])) @@ -123,10 +123,10 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3)) @@ -147,10 +147,10 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3), num_channels=3) @@ -172,11 +172,11 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) @@ -185,7 +185,7 @@ def test(): f=m.f, v=rn.v, num_verts=len(m.v), - light_pos=ch.array([-1000,-1000,-1000]), + light_pos=ch.array([-1000, -1000, -1000]), vc=m.vc, light_color=ch.array([1., 1., 1.])) @@ -209,17 +209,17 @@ def test(): # Assign attributes to renderer from opendr.util_tests import get_earthmesh -m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) +m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from opendr.camera import ProjectPoints -rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) +rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) vn = VertNormals(v=rn.v, f=rn.f) -sh_red = SphericalHarmonics(vn=vn, light_color=ch.array([1,0,0]), components=ch.random.randn(9)) -sh_green = SphericalHarmonics(vn=vn, light_color=ch.array([0,1,0]), components=ch.random.randn(9)) -sh_blue = SphericalHarmonics(vn=vn, light_color=ch.array([0,0,1]), components=ch.random.randn(9)) +sh_red = SphericalHarmonics(vn=vn, light_color=ch.array([1, 0, 0]), components=ch.random.randn(9)) +sh_green = SphericalHarmonics(vn=vn, light_color=ch.array([0, 1, 0]), components=ch.random.randn(9)) +sh_blue = SphericalHarmonics(vn=vn, light_color=ch.array([0, 0, 1]), components=ch.random.randn(9)) rn.vc = sh_red + sh_green + sh_blue # Show it @@ -232,34 +232,34 @@ def test(): """ demos['optimization'] = """ -from opendr.simple import * -import numpy as np +from opendr.simple import * +import numpy as np import matplotlib.pyplot as plt w, h = 320, 240 - + try: m = load_mesh('earth.obj') -except: +except: from opendr.util_tests import get_earthmesh - 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)) -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 + 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)) +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) translation[:] = translation.r + np.random.rand(3) rotation[:] = rotation.r + np.random.rand(3) *.2 @@ -273,46 +273,46 @@ def cb(_): import cv2 global E_raw cv2.imshow('Absolute difference', np.abs(E_raw.r)) - cv2.waitKey(1) + cv2.waitKey(1) -print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' +print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' free_variables=[translation, rotation, A.components] -ch.minimize({'pyr': E_pyr}, x0=free_variables, callback=cb) -ch.minimize({'raw': E_raw}, x0=free_variables, callback=cb) +ch.minimize({'pyr': E_pyr}, x0=free_variables, callback=cb) +ch.minimize({'raw': E_raw}, x0=free_variables, callback=cb) """ demos['optimization_cpl'] = """ -from opendr.simple import * -import numpy as np +from opendr.simple import * +import numpy as np import matplotlib.pyplot as plt w, h = 320, 240 - + try: m = load_mesh('earth.obj') -except: +except: from opendr.util_tests import get_earthmesh - 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)) -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) -model_v = translation + ch.array(V.r).dot(Rodrigues(rotation)) - -# Simulate an observed image + 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)) +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) +model_v = translation + ch.array(V.r).dot(Rodrigues(rotation)) + +# Simulate an observed image V[:] = model_v.r -observed = f.r +observed = f.r np.random.seed(1) translation[:] = translation.r + np.random.rand(3) @@ -328,12 +328,12 @@ def cb(_): import cv2 global E_raw cv2.imshow('Absolute difference', np.abs(E_raw.r)) - cv2.waitKey(1) + cv2.waitKey(1) -print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' +print 'OPTIMIZING TRANSLATION, ROTATION, AND LIGHT PARMS' free_variables=[translation, rotation, A.components, V] -ch.minimize({'pyr': E_pyr, 'cpl': (V - model_v)*1e-4}, x0=free_variables, callback=cb) -ch.minimize({'raw': E_raw, 'cpl': V - model_v}, x0=free_variables, callback=cb) +ch.minimize({'pyr': E_pyr, 'cpl': (V - model_v)*1e-4}, x0=free_variables, callback=cb) +ch.minimize({'raw': E_raw, 'cpl': V - model_v}, x0=free_variables, callback=cb) """ def demo(which=None): @@ -341,7 +341,7 @@ def demo(which=None): if which not in demos: print 'Please indicate which demo you want, as follows:' for key in demos: - print "\tdemo('%s')" % (key,) + print "\tdemo('%s')" % (key, ) return print '- - - - - - - - - - - - - - - - - - - - - - -' diff --git a/opendr/camera.py b/opendr/camera.py index c5e1875..e4b1805 100755 --- a/opendr/camera.py +++ b/opendr/camera.py @@ -30,11 +30,11 @@ class RigidTransform(Ch): dterms = 'v', 'rt', 't' def compute_r(self): - return (cv2.Rodrigues(self.rt.r)[0].dot(self.v.r.T) + col(self.t.r)).T.copy() + return(cv2.Rodrigues(self.rt.r)[0].dot(self.v.r.T) + col(self.t.r)).T.copy() def compute_dr_wrt(self, wrt): - if wrt not in (self.v, self.rt, self.t): + if wrt not in(self.v, self.rt, self.t): return if wrt is self.t: @@ -87,7 +87,7 @@ def compute_r(self): if np.any(self.t.r != 0.): v_t += self.t.r - x_y = v_t[:,:2] / v_t[:,[2]] + x_y = v_t[:, :2] / v_t[:, [2]] uv = x_y if np.any(self.k.r != 0.): k = self.k.r @@ -105,9 +105,9 @@ def compute_r(self): r2 = x2_y2.sum(axis=1) r4 = r2 ** 2. xy = x_y.prod(axis=1) - uv = x_y * (1 + k1 * r2 + k2 * r4 + k3 * r2 * r4)[:,np.newaxis] + uv = x_y * (1 + k1 * r2 + k2 * r4 + k3 * r2 * r4)[:, np.newaxis] uv += 2 * np.vstack([p1 * xy, p2 * xy]).T - uv += np.array([p2, p1]) * (r2[:,np.newaxis] + 2 * x2_y2) + uv += np.array([p2, p1]) * (r2[:, np.newaxis] + 2 * x2_y2) uv = self.f.r * uv + self.c.r return uv.squeeze() @@ -130,7 +130,7 @@ def compute_dr_wrt(self, wrt): rot = cv2.Rodrigues(self.rt.r)[0] data = np.asarray(j[:, 3:6].dot(rot), order='C').ravel() IS = np.repeat(np.arange(self.v.r.size*2/3), 3) - JS = np.asarray(np.repeat(np.arange(self.v.r.size).reshape((-1,3)), 2, axis=0), order='C').ravel() + JS = np.asarray(np.repeat(np.arange(self.v.r.size).reshape((-1, 3)), 2, axis=0), order='C').ravel() result = sp.csc_matrix((data, (IS, JS))) return result @@ -138,13 +138,13 @@ def unproject_points(self, uvd, camera_space=False): cam = ProjectPoints3D(**{k: getattr(self, k) for k in self.dterms if hasattr(self, k)}) try: - xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:,:2].reshape((1,-1,2))), np.asarray(cam.camera_mtx), cam.k.r) - xyz_camera_space = np.hstack((xy_undistorted_camspace.squeeze(), col(uvd[:,2]))) - xyz_camera_space[:,:2] *= col(xyz_camera_space[:,2]) # scale x,y by z + xy_undistorted_camspace = cv2.undistortPoints(np.asarray(uvd[:, :2].reshape((1, -1, 2))), np.asarray(cam.camera_mtx), cam.k.r) + xyz_camera_space = np.hstack((xy_undistorted_camspace.squeeze(), col(uvd[:, 2]))) + xyz_camera_space[:, :2] *= col(xyz_camera_space[:, 2]) # scale x, y by z if camera_space: return xyz_camera_space - other_answer = xyz_camera_space - row(cam.view_mtx[:,3]) # translate - result = other_answer.dot(cam.view_mtx[:,:3]) # rotate + other_answer = xyz_camera_space - row(cam.view_mtx[:, 3]) # translate + result = other_answer.dot(cam.view_mtx[:, :3]) # rotate except: # slow way, probably not so good. But doesn't require cv2.undistortPoints. cam.v = np.ones_like(uvd) ch.minimize(cam - uvd, x0=[cam.v], method='dogleg', options={'disp': 0}) @@ -165,18 +165,18 @@ def project_depth_point(self, xyz): uv = uvd[:2] / uvd[-1] return uv - @depends_on('f','c') + @depends_on('f', 'c') def camera_mtx(self): - return np.array([[self.f.r[0], 0, self.c.r[0]],[0., self.f.r[1], self.c.r[1]],[0.,0.,1.]], dtype=np.float64) + return np.array([[self.f.r[0], 0, self.c.r[0]], [0., self.f.r[1], self.c.r[1]], [0., 0., 1.]], dtype=np.float64) @depends_on('t', 'rt') def view_mtx(self): R = cv2.Rodrigues(self.rt.r)[0] - return np.hstack((R,col(self.t.r))) + return np.hstack((R, col(self.t.r))) @depends_on('v', 'rt', 't', 'f', 'c', 'k') def r_and_derivatives(self): - v = self.v.r.reshape((-1,3)).copy() + v = self.v.r.reshape((-1, 3)).copy() return cv2.projectPoints(v, self.rt.r, self.t.r, self.camera_mtx, self.k.r) @property @@ -194,8 +194,8 @@ def compute_r(self): @property def z_coords(self): - assert(self.v.r.shape[1]==3) - return RigidTransform(v=self.v, rt=self.rt, t=self.t)[:,2] + assert(self.v.r.shape[1] == 3) + return RigidTransform(v=self.v, rt=self.rt, t=self.t)[:, 2] def compute_dr_wrt(self, wrt): result = ProjectPoints.compute_dr_wrt(self, wrt) @@ -216,7 +216,7 @@ def compute_dr_wrt(self, wrt): if drz is not None: if sp.issparse(drz): drz = drz.todense() - bigger[:,2,:] = drz.reshape(bigger[:,2,:].shape) + bigger[:, 2, :] = drz.reshape(bigger[:, 2, :].shape) result = bigger.reshape((-1, bigger.shape[-1])) diff --git a/opendr/common.py b/opendr/common.py index 02bdd15..6833dba 100755 --- a/opendr/common.py +++ b/opendr/common.py @@ -49,7 +49,7 @@ def nangradients(arr): def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_width, image_height, num_verts, f, bnd_bool): """Construct a sparse jacobian that relates 2D projected vertex positions - (in the columns) to pixel values (in the rows). This can be done + (in the columns) to pixel values(in the rows). This can be done in two steps.""" n_channels = np.atleast_3d(observed).shape[2] @@ -90,7 +90,7 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid xdiffbnd = np.atleast_3d(xdiffbnd) # This corrects for a bias imposed boundary differences begin spread over two pixels - # (by np.gradients or similar) but only counted once (since OpenGL's line + # (by np.gradients or similar) but only counted once(since OpenGL's line # drawing spans 1 pixel) xdiffbnd *= 2.0 ydiffbnd *= 2.0 @@ -182,7 +182,7 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid def dImage_wrt_2dVerts(observed, visible, visibility, barycentric, image_width, image_height, num_verts, f): """Construct a sparse jacobian that relates 2D projected vertex positions - (in the columns) to pixel values (in the rows). This can be done + (in the columns) to pixel values(in the rows). This can be done in two steps.""" n_channels = np.atleast_3d(observed).shape[2] @@ -248,7 +248,7 @@ def flow_to(self, v_next, cam_next): # map 3d to 3d JS = col(self.f[visibility.ravel()[visible]]).ravel() IS = np.tile(col(np.arange(JS.size/3)), (1, 3)).ravel() - data = barycentric.reshape((-1,3))[visible].ravel() + data = barycentric.reshape((-1, 3))[visible].ravel() # replicate to xyz IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) @@ -395,7 +395,7 @@ def draw_visibility_image_internal(gl, v, f): def draw_colored_primitives(gl, v, f, fc=None): gl.EnableClientState(GL_VERTEX_ARRAY) - verts_by_face = np.asarray(v.reshape((-1,3))[f.ravel()], dtype=np.float64, order='C') + verts_by_face = np.asarray(v.reshape((-1, 3))[f.ravel()], dtype=np.float64, order='C') gl.VertexPointer(verts_by_face) if fc is not None: @@ -441,7 +441,7 @@ def draw_texcoord_image(glf, v, f, vt, ft, boundarybool_image=None): gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) - # want vtc: texture-coordinates per vertex (not per element in vc) + # want vtc: texture-coordinates per vertex(not per element in vc) colors = vt[ft.ravel()] colors = np.asarray(np.hstack((colors, col(colors[:, 0]*0))), np.float64, order='C') diff --git a/opendr/cvwrap.py b/opendr/cvwrap.py index bb033c5..7d5e392 100644 --- a/opendr/cvwrap.py +++ b/opendr/cvwrap.py @@ -1,4 +1,4 @@ try: import cv2 # pylint: disable=unused-import except: - raise Exception('Failed to import cv2 from the OpenCV distribution. Please install OpenCV with Python support. OpenCV may either be installed from http://opencv.org or installed with package managers such as Homebrew (on Mac, http://brew.sh) or apt-get (on Ubuntu or Debian).') + raise Exception('Failed to import cv2 from the OpenCV distribution. Please install OpenCV with Python support. OpenCV may either be installed from http://opencv.org or installed with package managers such as Homebrew(on Mac, http://brew.sh) or apt-get(on Ubuntu or Debian).') diff --git a/opendr/filters.py b/opendr/filters.py index ae45a91..615b585 100755 --- a/opendr/filters.py +++ b/opendr/filters.py @@ -69,7 +69,7 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level for ik in range(n_levels): cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape) cur_imshape = cur_obj.output_shape - output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label,ik)) + output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label, ik)) if not as_list: andit = lambda a : reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), a) @@ -82,7 +82,7 @@ def GaussianKernel2D(ksize, sigma): raise Exception('ksize should be an odd number') if sigma <= 0: raise Exception('sigma should be positive') - oneway = np.tile(cv2.getGaussianKernel(ksize,sigma), (1, ksize)) + oneway = np.tile(cv2.getGaussianKernel(ksize, sigma), (1, ksize)) return oneway * oneway.T @@ -150,8 +150,8 @@ def halfsampler_for(shape): w = int(shape[1]) d = int(shape[2]) if len(shape) > 2 else 1 - JS = np.arange(h*w*d).reshape((h,w,d)) - JS = JS[::2,::2,:] + JS = np.arange(h*w*d).reshape((h, w, d)) + JS = JS[::2, ::2, :] JS = JS.flatten() IS = np.arange(len(JS)) diff --git a/opendr/geometry.py b/opendr/geometry.py index 8cd062f..783bffb 100755 --- a/opendr/geometry.py +++ b/opendr/geometry.py @@ -9,78 +9,79 @@ __all__ = ['Rodrigues', 'VertNormals', 'TriNormals', 'TriNormalsScaled', 'CrossProduct', 'TriArea', 'AcosTriAngles', 'volume'] -from cvwrap import cv2 import numpy as np import scipy.sparse as sp from chumpy.utils import row, col -from chumpy import * import chumpy as ch -from chumpy.ch import MatVecMult -from topology import get_faces_per_edge, get_vert_connectivity +from chumpy.ch import MatVecMult, Ch, depends_on +from opendr.cvwrap import cv2 +from opendr.topology import get_faces_per_edge, get_vert_connectivity def volume(v, f): - # Construct a 3D matrix which is of size (nfaces x 3 x 3) + # Construct a 3D matrix which is of size(nfaces x 3 x 3) # Each row corresponds to a face; the third dimension indicates # which triangle in that face is being referred to vs = ch.dstack(( - v[f[:,0],:], - v[f[:,1],:], - v[f[:,2],:])) - - v321 = vs[:,0,2]*vs[:,1,1]*vs[:,2,0]; - v231 = vs[:,0,1]*vs[:,1,2]*vs[:,2,0]; - v312 = vs[:,0,2]*vs[:,1,0]*vs[:,2,1]; - v132 = vs[:,0,0]*vs[:,1,2]*vs[:,2,1]; - v213 = vs[:,0,1]*vs[:,1,0]*vs[:,2,2]; - v123 = vs[:,0,0]*vs[:,1,1]*vs[:,2,2]; - - volumes = (-v321 + v231 + v312 - v132 - v213 + v123) * (1./6.) + v[f[:, 0], :], + v[f[:, 1], :], + v[f[:, 2], :])) + + v321 = vs[:, 0, 2]*vs[:, 1, 1]*vs[:, 2, 0] + v231 = vs[:, 0, 1]*vs[:, 1, 2]*vs[:, 2, 0] + v312 = vs[:, 0, 2]*vs[:, 1, 0]*vs[:, 2, 1] + v132 = vs[:, 0, 0]*vs[:, 1, 2]*vs[:, 2, 1] + v213 = vs[:, 0, 1]*vs[:, 1, 0]*vs[:, 2, 2] + v123 = vs[:, 0, 0]*vs[:, 1, 1]*vs[:, 2, 2] + + volumes = (-v321 + v231 + v312 - v132 - v213 + v123) * (1./6.) return ch.abs(ch.sum(volumes)) class NormalizedNx3(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'v' - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'v' in which: - self.ss = np.sum(self.v.r.reshape(-1,3)**2, axis=1) - self.ss[self.ss==0] = 1e-10 + self.ss = np.sum(self.v.r.reshape(-1, 3)**2, axis=1) + self.ss[self.ss == 0] = 1e-10 self.s = np.sqrt(self.ss) self.s_inv = 1. / self.s def compute_r(self): - return (self.v.r.reshape(-1,3) / col(self.s)).reshape(self.v.r.shape) + return(self.v.r.reshape(-1, 3) / col(self.s)).reshape(self.v.r.shape) def compute_dr_wrt(self, wrt): if wrt is not self.v: return None - v = self.v.r.reshape(-1,3) - blocks = -np.einsum('ij,ik->ijk', v, v) * (self.ss**(-3./2.)).reshape((-1,1,1)) + v = self.v.r.reshape(-1, 3) + blocks = -np.einsum('ij, ik->ijk', v, v) * (self.ss**(-3./2.)).reshape((-1, 1, 1)) for i in range(3): - blocks[:,i,i] += self.s_inv + blocks[:, i, i] += self.s_inv if True: data = blocks.ravel() - indptr = np.arange(0,(self.v.r.size+1)*3,3) - indices = col(np.arange(0,self.v.r.size)) + indptr = np.arange(0, (self.v.r.size+1)*3, 3) + indices = col(np.arange(0, self.v.r.size)) indices = np.hstack([indices, indices, indices]) - indices = indices.reshape((-1,3,3)) - indices = indices.transpose((0,2,1)).ravel() + indices = indices.reshape((-1, 3, 3)) + indices = indices.transpose((0, 2, 1)).ravel() result = sp.csc_matrix((data, indices, indptr), shape=(self.v.r.size, self.v.r.size)) return result else: - matvec = lambda x : np.einsum('ijk,ik->ij', blocks, x.reshape((blocks.shape[0],3))).ravel() - return sp.linalg.LinearOperator((self.v.r.size,self.v.r.size), matvec=matvec) + matvec = lambda x: np.einsum('ijk, ik->ij', blocks, x.reshape((blocks.shape[0], 3))).ravel() + return sp.linalg.LinearOperator((self.v.r.size, self.v.r.size), matvec=matvec) class Sum3xN(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'v' def compute_r(self): - return np.sum(self.v.r.reshape((-1,3)), axis=1) + return np.sum(self.v.r.reshape((-1, 3)), axis=1) def compute_dr_wrt(self, wrt): if wrt is self.v: @@ -90,40 +91,41 @@ def compute_dr_wrt(self, wrt): result = sp.csc_matrix((data, (IS, JS)), shape=(self.v.r.size/3, self.v.r.size)) return result -class ndot(ch.Ch): +class ndot(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'mtx1', 'mtx2' def compute_r(self): - return np.einsum('abc,acd->abd', self.mtx1.r, self.mtx2.r) + return np.einsum('abc, acd->abd', self.mtx1.r, self.mtx2.r) def compute_d1(self): # To stay consistent with numpy, we must upgrade 1D arrays to 2D - mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape)<2 else self.mtx1.r - mtx2r = col(self.mtx2.r) if len(self.mtx2.r.shape)<2 else self.mtx2.r + mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape) < 2 else self.mtx1.r + mtx2r = col(self.mtx2.r) if len(self.mtx2.r.shape) < 2 else self.mtx2.r if mtx1r.ndim <= 2: - return sp.kron(sp.eye(mtx1r.shape[0], mtx1r.shape[0]),mtx2r.T) + return sp.kron(sp.eye(mtx1r.shape[0], mtx1r.shape[0]), mtx2r.T) else: mtx2f = mtx2r.reshape((-1, mtx2r.shape[-2], mtx2r.shape[-1])) mtx2f = np.rollaxis(mtx2f, -1, -2) #transpose basically - result = sp.block_diag([np.kron(np.eye(mtx1r.shape[-2], mtx1r.shape[-2]),m2) for m2 in mtx2f]) - assert(result.shape[0] == self.r.size) + result = sp.block_diag([np.kron(np.eye(mtx1r.shape[-2], mtx1r.shape[-2]), m2) for m2 in mtx2f]) + assert result.shape[0] == self.r.size return result def compute_d2(self): # To stay consistent with numpy, we must upgrade 1D arrays to 2D - mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape)<2 else self.mtx1.r - mtx2r = col(self.mtx2.r) if len(self.mtx2.r.shape)<2 else self.mtx2.r + mtx1r = row(self.mtx1.r) if len(self.mtx1.r.shape) < 2 else self.mtx1.r + mtx2r = col(self.mtx2.r) if len(self.mtx2.r.shape) < 2 else self.mtx2.r if mtx2r.ndim <= 1: return self.mtx1r elif mtx2r.ndim <= 2: - return sp.kron(mtx1r, sp.eye(mtx2r.shape[1],mtx2r.shape[1])) + return sp.kron(mtx1r, sp.eye(mtx2r.shape[1], mtx2r.shape[1])) else: mtx1f = mtx1r.reshape((-1, mtx1r.shape[-2], mtx1r.shape[-1])) - result = sp.block_diag([np.kron(m1, np.eye(mtx2r.shape[-1],mtx2r.shape[-1])) for m1 in mtx1f]) - assert(result.shape[0] == self.r.size) + result = sp.block_diag([np.kron(m1, np.eye(mtx2r.shape[-1], mtx2r.shape[-1])) for m1 in mtx1f]) + assert result.shape[0] == self.r.size return result @@ -138,27 +140,27 @@ def compute_dr_wrt(self, wrt): def face_bases(v, f): - t1 = TriEdges(f, 1, 0, v).reshape((-1,3)) - t2 = TriEdges(f, 2, 0, v).reshape((-1,3)) - #t3 = NormalizedNx3(CrossProduct(t1, t2)).reshape((-1,3)) - #t3 = CrossProduct(t1, t2).reshape((-1,3)) + t1 = TriEdges(f, 1, 0, v).reshape((-1, 3)) + t2 = TriEdges(f, 2, 0, v).reshape((-1, 3)) + #t3 = NormalizedNx3(CrossProduct(t1, t2)).reshape((-1, 3)) + #t3 = CrossProduct(t1, t2).reshape((-1, 3)) # Problem: cross-product is proportional in length to len(t1)*len(t2) # Solution: divide by sqrt(sqrt(len(cross-product))) - t3 = CrossProduct(t1, t2).reshape((-1,3)); t3 = t3 / col(ch.sum(t3**2., axis=1)**.25) - result = ch.hstack((t1, t2, t3)).reshape((-1,3,3)) + t3 = CrossProduct(t1, t2).reshape((-1, 3)); t3 = t3 / col(ch.sum(t3**2., axis=1)**.25) + result = ch.hstack((t1, t2, t3)).reshape((-1, 3, 3)) return result -def edge_defs(v,f): +def edge_defs(v, f): fb = face_bases(v, f) fpe = get_faces_per_edge(v.r, f) - return ndot(fb[fpe[:,0]], ch.linalg.inv(fb[fpe[:,1]])) + return ndot(fb[fpe[:, 0]], ch.linalg.inv(fb[fpe[:, 1]])) def FirstEdgesMtx(v, f, want_big=True): cnct = get_vert_connectivity((v.r if hasattr(v, 'r') else v), f) - nbrs = [np.nonzero(np.array(cnct[:,i].todense()))[0][0] for i in range(cnct.shape[1])] + nbrs = [np.nonzero(np.array(cnct[:, i].todense()))[0][0] for i in range(cnct.shape[1])] JS = np.array(nbrs) IS = np.arange(len(JS)) data = np.ones(IS.size) @@ -175,11 +177,11 @@ def FirstEdgesMtx(v, f, want_big=True): def SecondFundamentalForm(v, f): from chumpy import hstack, vstack from chumpy.linalg import Pinv - nbrs = MatVecMult(FirstEdgesMtx(v, f, want_big=True), v.ravel()).reshape((-1,3)) + nbrs = MatVecMult(FirstEdgesMtx(v, f, want_big=True), v.ravel()).reshape((-1, 3)) b0 = VertNormals(f=f, v=v) - b1 = NormalizedNx3(CrossProduct(b0, nbrs-v)).reshape((-1,3)) - b2 = NormalizedNx3(CrossProduct(b0, b1)).reshape((-1,3)) + b1 = NormalizedNx3(CrossProduct(b0, nbrs-v)).reshape((-1, 3)) + b2 = NormalizedNx3(CrossProduct(b0, b1)).reshape((-1, 3)) cnct = get_vert_connectivity(np.asarray(v), f) ffs = [] @@ -199,11 +201,12 @@ def SecondFundamentalForm(v, f): def GaussianCurvature(v, f): ff = SecondFundamentalForm(v, f) - result = ff[:,0] * ff[:,2] - ff[:,1]**2. + result = ff[:, 0] * ff[:, 2] - ff[:, 1]**2. return result class Rodrigues(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'rt' def compute_r(self): @@ -218,10 +221,10 @@ def TriArea(v_init, f, normalize): """ Returns a Ch object whose only attribute "v" represents the flattened vertices.""" if normalize: - nm = lambda x : NormalizedNx3(x) + nm = lambda x: NormalizedNx3(x) else: - nm = lambda x : x - result = Ch(lambda v : (Sum3xN(CrossProduct(TriEdges(f,1,0,nm(v)), TriEdges(f,2,0, nm(v)))**2.) ** 0.5) * 0.5) + nm = lambda x: x + result = Ch(lambda v: (Sum3xN(CrossProduct(TriEdges(f, 1, 0, nm(v)), TriEdges(f, 2, 0, nm(v)))**2.) ** 0.5) * 0.5) result.v = v_init return result @@ -230,25 +233,26 @@ def AcosTriAngles(v, f, normalize): """ Returns a Ch object whose only attribute "v" represents the flattened vertices.""" if normalize: - nm = lambda x : NormalizedNx3(x) + nm = lambda x: NormalizedNx3(x) else: - nm = lambda x : x + nm = lambda x: x - return Ch(lambda v : - Sum3xN(NormalizedNx3(TriEdges(f, 1, 0, nm(v))) * NormalizedNx3(TriEdges(f, 2, 0, nm(v)))) & - Sum3xN(NormalizedNx3(TriEdges(f, 2, 1, nm(v))) * NormalizedNx3(TriEdges(f, 0, 1, nm(v)))) & - Sum3xN(NormalizedNx3(TriEdges(f, 0, 2, nm(v))) * NormalizedNx3(TriEdges(f, 1, 2, nm(v))))) + return Ch(lambda v: + Sum3xN(NormalizedNx3(TriEdges(f, 1, 0, nm(v))) * NormalizedNx3(TriEdges(f, 2, 0, nm(v)))) & + Sum3xN(NormalizedNx3(TriEdges(f, 2, 1, nm(v))) * NormalizedNx3(TriEdges(f, 0, 1, nm(v)))) & + Sum3xN(NormalizedNx3(TriEdges(f, 0, 2, nm(v))) * NormalizedNx3(TriEdges(f, 1, 2, nm(v))))) class VertNormals(Ch): - """If normalized==True, normals are normalized; otherwise they'll be about as long as neighboring edges.""" + """If normalized == True, normals are normalized; otherwise they'll be about as long as neighboring edges.""" + # pylint: disable=attribute-defined-outside-init dterms = 'v' terms = 'f', 'normalized' term_order = 'v', 'f', 'normalized' - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if not hasattr(self, 'normalized'): self.normalized = True @@ -270,7 +274,7 @@ def on_changed(self, which): sz = self.v.size self.faces_by_vertex = sp.csc_matrix((data, (IS, JS)), shape=(sz, f.size)) - self.tns = Ch(lambda v : CrossProduct(TriEdges(f,1,0,v), TriEdges(f,2,0, v))) + self.tns = Ch(lambda v: CrossProduct(TriEdges(f, 1, 0, v), TriEdges(f, 2, 0, v))) self.tns.v = self.v if self.normalized: @@ -279,14 +283,14 @@ def on_changed(self, which): else: test = self.faces_by_vertex.dot(np.ones(self.faces_by_vertex.shape[1])) faces_by_vertex = sp.diags([1. / test], [0]).dot(self.faces_by_vertex).tocsc() - normals = MatVecMult(faces_by_vertex, self.tns).reshape((-1,3)) - normals = normals / (ch.sum(normals**2, axis=1) ** .25).reshape((-1,1)) + normals = MatVecMult(faces_by_vertex, self.tns).reshape((-1, 3)) + normals = normals / (ch.sum(normals**2, axis=1) ** .25).reshape((-1, 1)) self.normals = normals def compute_r(self): - return self.normals.r.reshape((-1,3)) + return self.normals.r.reshape((-1, 3)) def compute_dr_wrt(self, wrt): if wrt is self.v: @@ -295,14 +299,15 @@ def compute_dr_wrt(self, wrt): def TriNormals(v, f): - return NormalizedNx3(TriNormalsScaled(v,f)) + return NormalizedNx3(TriNormalsScaled(v, f)) def TriNormalsScaled(v, f): - return CrossProduct(TriEdges(f,1,0,v), TriEdges(f,2,0, v)) + return CrossProduct(TriEdges(f, 1, 0, v), TriEdges(f, 2, 0, v)) class TriEdges(Ch): + # pylint: disable=attribute-defined-outside-init terms = 'f', 'cplus', 'cminus' dterms = 'v' @@ -317,37 +322,38 @@ def compute_dr_wrt(self, wrt): cplus = self.cplus cminus = self.cminus - vplus = self.f[:,cplus] - vminus = self.f[:,cminus] + vplus = self.f[:, cplus] + vminus = self.f[:, cminus] vplus3 = row(np.hstack([col(vplus*3), col(vplus*3+1), col(vplus*3+2)])) vminus3 = row(np.hstack([col(vminus*3), col(vminus*3+1), col(vminus*3+2)])) - IS = row(np.arange(0,vplus3.size)) + IS = row(np.arange(0, vplus3.size)) ones = np.ones(vplus3.size) shape = (self.f.size, self.v.r.size) return sp.csc_matrix((ones, np.vstack([IS, vplus3])), shape=shape) - sp.csc_matrix((ones, np.vstack([IS, vminus3])), shape=shape) def _edges_for(v, f, cplus, cminus): - return ( - v.reshape(-1,3)[f[:,cplus],:] - - v.reshape(-1,3)[f[:,cminus],:]).ravel() + return( + v.reshape(-1, 3)[f[:, cplus], :] - + v.reshape(-1, 3)[f[:, cminus], :]).ravel() class CrossProduct(Ch): + # pylint: disable=attribute-defined-outside-init terms = [] dterms = 'a', 'b' - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'a' in which: - a = self.a.r.reshape((-1,3)) - self.a1 = a[:,0] - self.a2 = a[:,1] - self.a3 = a[:,2] + a = self.a.r.reshape((-1, 3)) + self.a1 = a[:, 0] + self.a2 = a[:, 1] + self.a3 = a[:, 2] if 'b' in which: - b = self.b.r.reshape((-1,3)) - self.b1 = b[:,0] - self.b2 = b[:,1] - self.b3 = b[:,2] + b = self.b.r.reshape((-1, 3)) + self.b1 = b[:, 0] + self.b2 = b[:, 1] + self.b3 = b[:, 2] def compute_r(self): @@ -355,17 +361,17 @@ def compute_r(self): # TODO: check fortran ordering? return _call_einsum_matvec(self.Ax, self.b.r) - def compute_dr_wrt(self, obj): - if obj not in (self.a, self.b): + def compute_dr_wrt(self, obj): # pylint: disable=arguments-differ + if obj not in(self.a, self.b): return None sz = self.a.r.size if not hasattr(self, 'indices') or self.indices.size != sz*3: - self.indptr = np.arange(0,(sz+1)*3,3) - idxs = col(np.arange(0,sz)) + self.indptr = np.arange(0, (sz+1)*3, 3) + idxs = col(np.arange(0, sz)) idxs = np.hstack([idxs, idxs, idxs]) - idxs = idxs.reshape((-1,3,3)) - idxs = idxs.transpose((0,2,1)).ravel() + idxs = idxs.reshape((-1, 3, 3)) + idxs = idxs.transpose((0, 2, 1)).ravel() self.indices = idxs if obj is self.a: @@ -430,17 +436,9 @@ def Bx(self): def _call_einsum_matvec(m, righthand): - r = righthand.reshape(m.shape[0],3) - return np.einsum('ijk,ik->ij', m, r).ravel() + r = righthand.reshape(m.shape[0], 3) + return np.einsum('ijk, ik->ij', m, r).ravel() def _call_einsum_matmat(m, righthand): - r = righthand.reshape(m.shape[0],3,-1) - return np.einsum('ijk,ikm->ijm', m, r).reshape(-1,r.shape[2]) - -def main(): - pass - - -if __name__ == '__main__': - main() - + r = righthand.reshape(m.shape[0], 3, -1) + return np.einsum('ijk, ikm->ijm', m, r).reshape(-1, r.shape[2]) diff --git a/opendr/lighting.py b/opendr/lighting.py index 4213a4b..7711a7b 100755 --- a/opendr/lighting.py +++ b/opendr/lighting.py @@ -9,16 +9,17 @@ __all__ = ['LambertianPointLight', 'SphericalHarmonics'] -import os, sys, logging +import os +import sys +import logging import numpy as np -import scipy.sparse as sp import scipy - -from chumpy.utils import row, col +import scipy.sparse as sp import chumpy as ch +from chumpy.utils import row, col from chumpy.ch import Ch -from geometry import VertNormals from chumpy import multiply, maximum +from opendr.geometry import VertNormals logger = logging.getLogger(__name__) @@ -26,22 +27,23 @@ def real_sh_coeff(xyz_samples): d_sqrt_pi = 2*np.sqrt(np.pi) real_coeff = np.zeros((len(xyz_samples), 9)) - real_coeff[:,0] = 1/d_sqrt_pi + real_coeff[:, 0] = 1/d_sqrt_pi - real_coeff[:,1] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,0] - real_coeff[:,2] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,2] - real_coeff[:,3] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,1] + real_coeff[:, 1] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 0] + real_coeff[:, 2] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 2] + real_coeff[:, 3] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 1] - real_coeff[:,4] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,1] - real_coeff[:,5] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,1]*xyz_samples[:,2] - real_coeff[:,6] = (np.sqrt(5)/(2*d_sqrt_pi))*(3*xyz_samples[:,2]**2-1) - real_coeff[:,7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,2] - real_coeff[:,8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:,0]**2 - xyz_samples[:,1]**2) + real_coeff[:, 4] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 0]*xyz_samples[:, 1] + real_coeff[:, 5] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 1]*xyz_samples[:, 2] + real_coeff[:, 6] = (np.sqrt(5)/(2*d_sqrt_pi))*(3*xyz_samples[:, 2]**2-1) + real_coeff[:, 7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 0]*xyz_samples[:, 2] + real_coeff[:, 8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:, 0]**2 - xyz_samples[:, 1]**2) return real_coeff class SphericalHarmonics(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'vn', 'components' terms = ['light_color'] @@ -49,26 +51,26 @@ class SphericalHarmonics(Ch): K = np.array([ 1./d_sqrt_pi, np.sqrt(3)/d_sqrt_pi, - np.sqrt(3)/d_sqrt_pi, - np.sqrt(3)/d_sqrt_pi, - np.sqrt(15)/d_sqrt_pi, - np.sqrt(15)/d_sqrt_pi, + np.sqrt(3)/d_sqrt_pi, + np.sqrt(3)/d_sqrt_pi, + np.sqrt(15)/d_sqrt_pi, + np.sqrt(15)/d_sqrt_pi, np.sqrt(5)/(2*d_sqrt_pi), - np.sqrt(15)/d_sqrt_pi, - np.sqrt(15)/(2*d_sqrt_pi)]) + np.sqrt(15)/d_sqrt_pi, + np.sqrt(15)/(2*d_sqrt_pi)]) @property def num_channels(self): return self.light_color.size - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'vn' in which: - vn = self.vn.r.reshape((-1,3)) + vn = self.vn.r.reshape((-1, 3)) # Conversion from normals to spherical harmonics found in... # http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates - self.theta = np.arccos(vn[:,2]) - self.phi = np.arctan2(vn[:,1], vn[:,0]) + self.theta = np.arccos(vn[:, 2]) + self.phi = np.arctan2(vn[:, 1], vn[:, 0]) self.sh_coeffs = real_sh_coeff(vn) self.num_verts = self.sh_coeffs.shape[0] @@ -78,48 +80,48 @@ def on_changed(self, which): IS = np.arange(self.num_verts*nc) JS = np.repeat(np.arange(self.num_verts), nc) data = (row(self.light_color)*np.ones((self.num_verts, nc))).ravel() - self.mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*nc, self.num_verts)) + self.mtx = sp.csc_matrix((data, (IS, JS)), shape=(self.num_verts*nc, self.num_verts)) def compute_r(self): comps = self.components.r n = len(comps) - result = self.mtx.dot(self.sh_coeffs[:,:n].dot(col(self.components.r))) - result[result<0] = 0 - return result.reshape((-1,self.num_channels)) + result = self.mtx.dot(self.sh_coeffs[:, :n].dot(col(self.components.r))) + result[result < 0] = 0 + return result.reshape((-1, self.num_channels)) def compute_dr_wrt(self, wrt): comps = np.zeros(9) comps[:len(self.components.r)] = self.components.r comps = comps * self.K.ravel() if wrt is self.vn: - vn = self.vn.r.reshape((-1,3)) + vn = self.vn.r.reshape((-1, 3)) - #real_coeff[:,1] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,0] + #real_coeff[:, 1] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 0] VS0 = np.ones(self.sh_coeffs.shape[0]) * comps[1] - #real_coeff[:,2] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,2] + #real_coeff[:, 2] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 2] VS1 = np.ones(self.sh_coeffs.shape[0]) * comps[3] - #real_coeff[:,3] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:,1] + #real_coeff[:, 3] = (np.sqrt(3)/d_sqrt_pi)*xyz_samples[:, 1] VS2 = np.ones(self.sh_coeffs.shape[0]) * comps[2] - #real_coeff[:,4] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,1] - VS0 += vn[:,1] * comps[4] - VS1 += vn[:,0] * comps[4] + #real_coeff[:, 4] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 0]*xyz_samples[:, 1] + VS0 += vn[:, 1] * comps[4] + VS1 += vn[:, 0] * comps[4] - #real_coeff[:,5] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,1]*xyz_samples[:,2] - VS1 += vn[:,2]*comps[5] - VS2 += vn[:,1]*comps[5] + #real_coeff[:, 5] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 1]*xyz_samples[:, 2] + VS1 += vn[:, 2]*comps[5] + VS2 += vn[:, 1]*comps[5] - #real_coeff[:,6] = (np.sqrt(5)/2*d_sqrt_pi)*(3*xyz_samples[:,2]**2-1) - VS2 += 6*vn[:,2] * comps[6] + #real_coeff[:, 6] = (np.sqrt(5)/2*d_sqrt_pi)*(3*xyz_samples[:, 2]**2-1) + VS2 += 6*vn[:, 2] * comps[6] - #real_coeff[:,7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:,0]*xyz_samples[:,2] - VS0 += vn[:,2] * comps[7] - VS2 += vn[:,0] * comps[7] + #real_coeff[:, 7] = (np.sqrt(15)/d_sqrt_pi)*xyz_samples[:, 0]*xyz_samples[:, 2] + VS0 += vn[:, 2] * comps[7] + VS2 += vn[:, 0] * comps[7] - #real_coeff[:,8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:,0]**2 - xyz_samples[:,1]**2) - VS0 += 2. * vn[:,0] * comps[8] - VS1 -= 2. * vn[:,1] * comps[8] + #real_coeff[:, 8] = (np.sqrt(15)/(2*d_sqrt_pi))*(xyz_samples[:, 0]**2 - xyz_samples[:, 1]**2) + VS0 += 2. * vn[:, 0] * comps[8] + VS1 -= 2. * vn[:, 1] * comps[8] rng = np.arange(self.sh_coeffs.shape[0]) IS = np.concatenate((rng, rng, rng)) @@ -130,11 +132,11 @@ def compute_dr_wrt(self, wrt): elif wrt is self.components: comps = self.components.r n = len(comps) - result = self.mtx.dot(self.sh_coeffs[:,:n]) + result = self.mtx.dot(self.sh_coeffs[:, :n]) else: return None - which = np.nonzero(self.r.ravel()>0)[0] + which = np.nonzero(self.r.ravel() > 0)[0] data = np.ones_like(which) gr_equal_zero = sp.csc_matrix((data, (which, which)), shape=(self.r.size, self.r.size)) @@ -147,7 +149,7 @@ def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_ :param vn: vertex normals :param light_pos: light position :param light_dir: light direction - :param spot_exponent: spot exponent (a la opengl) + :param spot_exponent: spot exponent(a la opengl) :param camcoord: if True, then pos and dir are wrt the camera :param camera_t: 3-vector indicating translation of camera :param camera_rt: 3-vector indicating direction of camera @@ -155,17 +157,17 @@ def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_ """ if camcoord: # Transform pos and dir from camera to world coordinate system - assert(camera_t is not None and camera_rt is not None) + assert camera_t is not None and camera_rt is not None from opendr.geometry import Rodrigues rot = Rodrigues(rt=camera_rt) pos = rot.T.dot(pos-camera_t) dir = rot.T.dot(dir) dir = dir / ch.sqrt(ch.sum(dir**2.)) - v_minus_light = v - pos.reshape((1,3)) + v_minus_light = v - pos.reshape((1, 3)) v_distances = ch.sqrt(ch.sum(v_minus_light**2, axis=1)) - v_minus_light_normed = v_minus_light / v_distances.reshape((-1,1)) - cosangle = v_minus_light_normed.dot(dir.reshape((3,1))) + v_minus_light_normed = v_minus_light / v_distances.reshape((-1, 1)) + cosangle = v_minus_light_normed.dot(dir.reshape((3, 1))) light_dot_normal = ch.sum(vn*v_minus_light_normed, axis=1) light_dot_normal.label = 'light_dot_normal' cosangle.label = 'cosangle' @@ -180,10 +182,11 @@ def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_ class LambertianPointLight(Ch): + # pylint: disable=attribute-defined-outside-init terms = 'f', 'num_verts', 'light_color', 'double_sided' dterms = 'light_pos', 'v', 'vc', 'vn' - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if not hasattr(self, '_lpl'): if getattr(self, 'double_sided', False): from chumpy.ch import abs as absolute @@ -200,21 +203,21 @@ def on_changed(self, which): if 'v' in which and hasattr(self.vn, 'needs_autoupdate') and self.vn.needs_autoupdate: self.vn.v = self.v - ldn_args = {k: getattr(self, k) for k in which if k in ('light_pos', 'v', 'vn')} + ldn_args = {k: getattr(self, k) for k in which if k in('light_pos', 'v', 'vn')} if len(ldn_args) > 0: self.ldn.set(**ldn_args) - self._lpl.a.a.a = self.ldn.reshape((-1,1)) + self._lpl.a.a.a = self.ldn.reshape((-1, 1)) if 'num_verts' in which or 'light_color' in which: # nc = self.num_channels # IS = np.arange(self.num_verts*nc) # JS = np.repeat(np.arange(self.num_verts), 3) # data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() - # mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) - self._lpl.a.a.b = self.light_color.reshape((1,self.num_channels)) + # mtx = sp.csc_matrix((data, (IS, JS)), shape=(self.num_verts*3, self.num_verts)) + self._lpl.a.a.b = self.light_color.reshape((1, self.num_channels)) if 'vc' in which: - self._lpl.a.b = self.vc.reshape((-1,self.num_channels)) + self._lpl.a.b = self.vc.reshape((-1, self.num_channels)) @property def num_channels(self): @@ -228,7 +231,6 @@ def compute_dr_wrt(self, wrt): return 1 - # def compute_light_repeat(num_verts): # IS = np.arange(num_verts*3) # JS = IS % 3 @@ -238,18 +240,8 @@ def compute_dr_wrt(self, wrt): def LightDotNormal(num_verts): - normalize_rows = lambda v : v / col(ch.sqrt(ch.sum(v.reshape((-1,3))**2, axis=1))) - sum_rows = lambda v : ch.sum(v.reshape((-1,3)), axis=1) + normalize_rows = lambda v: v / col(ch.sqrt(ch.sum(v.reshape((-1, 3))**2, axis=1))) + sum_rows = lambda v: ch.sum(v.reshape((-1, 3)), axis=1) return Ch(lambda light_pos, v, vn : - sum_rows(normalize_rows(light_pos.reshape((1,3)) - v.reshape((-1,3))) * vn.reshape((-1,3)))) - - - -def main(): - pass - - -if __name__ == '__main__': - main() - + sum_rows(normalize_rows(light_pos.reshape((1, 3)) - v.reshape((-1, 3))) * vn.reshape((-1, 3)))) diff --git a/opendr/renderer.py b/opendr/renderer.py index 4171e6b..2fead21 100755 --- a/opendr/renderer.py +++ b/opendr/renderer.py @@ -9,37 +9,35 @@ __all__ = ['ColoredRenderer', 'TexturedRenderer', 'DepthRenderer'] -import numpy as np -from cvwrap import cv2 -import time import platform -import scipy.sparse as sp from copy import deepcopy -import common -from common import draw_visibility_image, draw_barycentric_image, draw_colored_primitives, draw_texcoord_image -from topology import get_vertices_per_edge, get_faces_per_edge - -if platform.system()=='Darwin': - from contexts.ctx_mac import OsContext -else: - from contexts.ctx_mesa import OsContext - -from chumpy import * # pylint: disable=wildcard-import, unused-wildcard-import -from contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import +import numpy as np +import scipy.sparse as sp +from chumpy.ch import Ch, depends_on from chumpy.utils import row, col - +from opendr.contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import +from opendr.cvwrap import cv2 +from opendr.common import draw_visibility_image, draw_barycentric_image, draw_colored_primitives, draw_texcoord_image +from opendr.common import dImage_wrt_2dVerts_bnd, dImage_wrt_2dVerts, dr_wrt_vc, dr_wrt_bgcolor +from opendr.topology import get_vertices_per_edge, get_faces_per_edge + +if platform.system() == 'Darwin': + from opendr.contexts.ctx_mac import OsContext # pylint: disable=no-name-in-module +else: + from opendr.contexts.ctx_mesa import OsContext # pylint: disable=no-name-in-module pixel_center_offset = 0.5 class BaseRenderer(Ch): - terms = ['f', 'frustum','overdraw'] + # pylint: disable=attribute-defined-outside-init + terms = ['f', 'frustum', 'overdraw'] dterms = ['camera', 'v'] @depends_on('f') # not v: specifically, it depends only on the number of vertices, not on the values in v def primitives_per_edge(self): - v=self.v.r.reshape((-1,3)) - f=self.f + v = self.v.r.reshape((-1, 3)) + f = self.f vpe = get_vertices_per_edge(v, f) fpe = get_faces_per_edge(v, f, vpe) return fpe, vpe @@ -88,16 +86,18 @@ def fpe(self): class DepthRenderer(BaseRenderer): - terms = 'f', 'frustum', 'background_image','overdraw', 'x0', 'x1', 'y0', 'y1' + # pylint: disable=attribute-defined-outside-init + terms = 'f', 'frustum', 'background_image', 'overdraw', 'x0', 'x1', 'y0', 'y1' dterms = 'camera', 'v' + USE_BARYCENTRIC = True @property def shape(self): - return (self.frustum['height'], self.frustum['width']) + return(self.frustum['height'], self.frustum['width']) def compute_r(self): - tmp = self.camera.r + _ = self.camera.r return self.depth_image.reshape((self.frustum['height'], self.frustum['width'])) def compute_dr_wrt(self, wrt): @@ -109,13 +109,12 @@ def compute_dr_wrt(self, wrt): visible = np.nonzero(visibility.ravel() != 4294967295)[0] barycentric = self.barycentric_image if wrt is self.camera: - shape = visibility.shape depth = self.depth_image if self.overdraw: - result1 = common.dImage_wrt_2dVerts_bnd(depth, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f, self.boundaryid_image != 4294967295) + result1 = dImage_wrt_2dVerts_bnd(depth, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f, self.boundaryid_image != 4294967295) else: - result1 = common.dImage_wrt_2dVerts(depth, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) + result1 = dImage_wrt_2dVerts(depth, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) # result1 = common.dImage_wrt_2dVerts(depth, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) @@ -134,25 +133,25 @@ def compute_dr_wrt(self, wrt): [self.camera.c.r[0], self.camera.c.r[1], 1] ]) pts = self.camera.unproject_points(pts) - cam_axis = pts[0,:] - pts[1,:] + cam_axis = pts[0, :] - pts[1, :] - if True: # use barycentric coordinates (correct way) + if self.USE_BARYCENTRIC: # use barycentric coordinates(correct way) w = visibility.shape[1] pxs = np.asarray(visible % w, np.int32) pys = np.asarray(np.floor(np.floor(visible) / w), np.int32) bc0 = col(barycentric[pys, pxs, 0]) bc1 = col(barycentric[pys, pxs, 1]) bc2 = col(barycentric[pys, pxs, 2]) - bc = np.hstack((bc0,bc0,bc0,bc1,bc1,bc1,bc2,bc2,bc2)).ravel() - else: # each vert contributes equally (an approximation) + bc = np.hstack((bc0, bc0, bc0, bc1, bc1, bc1, bc2, bc2, bc2)).ravel() + else: # each vert contributes equally(an approximation) bc = 1. / 3. - data = np.tile(row(cam_axis), (IS.size/3,1)).ravel() * bc + data = np.tile(row(cam_axis), (IS.size/3, 1)).ravel() * bc result2 = sp.csc_matrix((data, (IS, JS)), shape=(self.frustum['height']*self.frustum['width'], self.v.r.size)) return result2 - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'frustum' in which: w = self.frustum['width'] @@ -170,7 +169,7 @@ def on_changed(self, which): if not hasattr(self, 'overdraw'): self.overdraw = True - assert(self.v is self.camera.v) + assert self.v is self.camera.v @depends_on(dterms+terms) @@ -178,7 +177,7 @@ def depth_image(self): self._call_on_changed() gl = self.glb - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) draw_noncolored_verts(gl, self.camera.v.r, self.f) @@ -193,13 +192,13 @@ def depth_image(self): result = overdraw*boundarybool_image + result*(1-boundarybool_image) if hasattr(self, 'background_image'): - if False: # has problems at boundaries, not sure why yet - bg_px = self.visibility_image == 4294967295 - fg_px = 1 - bg_px - result = bg_px * self.background_image + fg_px * result - else: - tmp = np.concatenate((np.atleast_3d(result), np.atleast_3d(self.background_image)), axis=2) - result = np.min(tmp, axis=2) + # The following has problems at boundaries, not sure why yet: + # bg_px = self.visibility_image == 4294967295 + # fg_px = 1 - bg_px + # result = bg_px * self.background_image + fg_px * result + # For the moment, go with: + tmp = np.concatenate((np.atleast_3d(result), np.atleast_3d(self.background_image)), axis=2) + result = np.min(tmp, axis=2) return result @@ -219,22 +218,22 @@ def boundaryid_image(self): self._call_on_changed() if hasattr(self, 'x0') and self.x0 != None: return draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, - self.fpe, self.camera, - self.x0, self.x1, self.y0, self.y1) + self.fpe, self.camera, + self.x0, self.x1, self.y0, self.y1) else: return draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, - self.fpe, self.camera) + self.fpe, self.camera) @depends_on('f', 'frustum', 'camera', 'overdraw', 'x0', 'x1', 'y0', 'y1') def barycentric_image(self): self._call_on_changed() if hasattr(self, 'x0') and self.x0 != None: return draw_barycentric_image(self.glf, self.v.r, self.f, - self.boundarybool_image if self.overdraw else None, - self.x0, self.x1, self.y0, self.y1) + self.boundarybool_image if self.overdraw else None, + self.x0, self.x1, self.y0, self.y1) else: return draw_barycentric_image(self.glf, self.v.r, self.f, - self.boundarybool_image if self.overdraw else None) + self.boundarybool_image if self.overdraw else None) def getDepthMesh(self, depth_image=None): self._call_on_changed() # make everything is up-to-date @@ -244,26 +243,27 @@ def getDepthMesh(self, depth_image=None): idxs = np.arange(w*h).reshape((h, w)) # v0 is upperleft, v1 is upper right, v2 is lowerleft, v3 is lowerright - v0 = col(idxs[:-1,:-1]) - v1 = col(idxs[:-1,1:]) - v2 = col(idxs[1:,:-1]) - v3 = col(idxs[1:,1:]) + v0 = col(idxs[:-1, :-1]) + v1 = col(idxs[:-1, 1:]) + v2 = col(idxs[1:, :-1]) + v3 = col(idxs[1:, 1:]) - f = np.hstack((v0, v1, v2, v1, v3, v2)).reshape((-1,3)) + f = np.hstack((v0, v1, v2, v1, v3, v2)).reshape((-1, 3)) return v, f class BoundaryRenderer(BaseRenderer): + # pylint: disable=attribute-defined-outside-init terms = 'f', 'frustum', 'num_channels' dterms = 'camera', @property def shape(self): - return (self.frustum['height'], self.frustum['width'], self.num_channels) + return(self.frustum['height'], self.frustum['width'], self.num_channels) def compute_r(self): - tmp = self.camera.r + _ = self.camera.r return self.color_image def compute_dr_wrt(self, wrt): @@ -271,16 +271,14 @@ def compute_dr_wrt(self, wrt): return None visibility = self.boundaryid_image - shape = visibility.shape visible = np.nonzero(visibility.ravel() != 4294967295)[0] - num_visible = len(visible) barycentric = self.barycentric_image - return common.dImage_wrt_2dVerts(self.color_image, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.vpe) + return dImage_wrt_2dVerts(self.color_image, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.vpe) - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'frustum' in which: w = self.frustum['width'] h = self.frustum['height'] @@ -300,10 +298,11 @@ def on_changed(self, which): def color_image(self): self._call_on_changed() result = self.boundarybool_image.astype(np.float64) - return np.dstack([result for i in range(self.num_channels)]) + return np.dstack([result for _ in range(self.num_channels)]) class ColoredRenderer(BaseRenderer): + # pylint: disable=attribute-defined-outside-init terms = 'f', 'frustum', 'background_image', 'overdraw', 'num_channels' dterms = 'vc', 'camera', 'bgcolor' @@ -312,12 +311,12 @@ def shape(self): if not hasattr(self, 'num_channels'): self.num_channels = 3 if self.num_channels > 1: - return (self.frustum['height'], self.frustum['width'], self.num_channels) + return(self.frustum['height'], self.frustum['width'], self.num_channels) else: - return (self.frustum['height'], self.frustum['width']) + return(self.frustum['height'], self.frustum['width']) def compute_r(self): - tmp = self.camera.r + _ = self.camera.r return self.color_image # .reshape((self.frustum['height'], self.frustum['width'], -1)).squeeze() def compute_dr_wrt(self, wrt): @@ -326,28 +325,26 @@ def compute_dr_wrt(self, wrt): visibility = self.visibility_image - shape = visibility.shape color = self.color_image visible = np.nonzero(visibility.ravel() != 4294967295)[0] - num_visible = len(visible) barycentric = self.barycentric_image if wrt is self.camera: if self.overdraw: - return common.dImage_wrt_2dVerts_bnd(color, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f, self.boundaryid_image != 4294967295) + return dImage_wrt_2dVerts_bnd(color, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f, self.boundaryid_image != 4294967295) else: - return common.dImage_wrt_2dVerts(color, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) + return dImage_wrt_2dVerts(color, visible, visibility, barycentric, self.frustum['width'], self.frustum['height'], self.v.r.size/3, self.f) elif wrt is self.vc: - return common.dr_wrt_vc(visible, visibility, self.f, barycentric, self.frustum, self.vc.size, num_channels=self.num_channels) + return dr_wrt_vc(visible, visibility, self.f, barycentric, self.frustum, self.vc.size, num_channels=self.num_channels) elif wrt is self.bgcolor: - return common.dr_wrt_bgcolor(visibility, self.frustum, num_channels=self.num_channels) + return dr_wrt_bgcolor(visibility, self.frustum, num_channels=self.num_channels) - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if 'frustum' in which: w = int(self.frustum['width']) h = int(self.frustum['height']) @@ -370,12 +367,13 @@ def on_changed(self, which): if not hasattr(self, 'overdraw'): self.overdraw = True - if 'bgcolor' in which or ('frustum' in which and hasattr(self, 'bgcolor')): + if 'bgcolor' in which or('frustum' in which and hasattr(self, 'bgcolor')): self.glf.ClearColor(self.bgcolor.r[0], self.bgcolor.r[1%self.num_channels], self.bgcolor.r[2%self.num_channels], 1.) def flow_to(self, v_next, cam_next=None): - return common.flow_to(self, v_next, cam_next) + from opendr.common import flow_to as _flow_to + return _flow_to(self, v_next, cam_next) def filter_for_triangles(self, which_triangles): cim = self.color_image @@ -390,24 +388,31 @@ def filter_for_triangles(self, which_triangles): ys = relevant_pixels / vim.shape[1] return cim2[np.min(ys):np.max(ys), np.min(xs):np.max(xs), :] - + # FIXME WHICH ONE IS REAL???? @depends_on('f', 'camera', 'vc') def boundarycolor_image(self): return self.draw_boundarycolor_image(with_vertex_colors=True) - + # @depends_on(terms+dterms) + # def boundarycolor_image(self): + # self._call_on_changed() + # gl = self.glf + # colors = self.vc.r.reshape((-1, 3))[self.vpe.ravel()] + # gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + # draw_colored_primitives(gl, self.v.r.reshape((-1, 3)), self.vpe, colors) + # return np.asarray(deepcopy(gl.getImage()), np.float64) def draw_color_image(self, gl): self._call_on_changed() - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # use face colors if given # FIXME: this won't work for 2 channels draw_colored_verts(gl, self.v.r, self.f, self.vc.r) - result = np.asarray(deepcopy(gl.getImage()[:,:,:self.num_channels].squeeze()), np.float64) + result = np.asarray(deepcopy(gl.getImage()[:, :, :self.num_channels].squeeze()), np.float64) if hasattr(self, 'background_image'): - bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,self.num_channels)).squeeze() + bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1, 1, self.num_channels)).squeeze() fg_px = 1 - bg_px result = bg_px * self.background_image + fg_px * result @@ -434,19 +439,10 @@ def color_image(self): @depends_on('f', 'frustum', 'camera') def boundary_images(self): self._call_on_changed() - return draw_boundary_images(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera) - - @depends_on(terms+dterms) - def boundarycolor_image(self): - self._call_on_changed() - gl = self.glf - colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - draw_colored_primitives(gl, self.v.r.reshape((-1,3)), self.vpe, colors) - return np.asarray(deepcopy(gl.getImage()), np.float64) - + return draw_boundary_images(self.glf, self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera) class TexturedRenderer(ColoredRenderer): + # pylint: disable=attribute-defined-outside-init terms = 'f', 'frustum', 'vt', 'ft', 'background_image', 'overdraw' dterms = 'vc', 'camera', 'bgcolor', 'texture_image' @@ -455,7 +451,7 @@ def __del__(self): @property def shape(self): - return (self.frustum['height'], self.frustum['width'], 3) + return(self.frustum['height'], self.frustum['width'], 3) @property def num_channels(self): @@ -480,15 +476,10 @@ def compute_dr_wrt(self, wrt): clr_im = self.draw_color_image(with_vertex_colors=True, with_texture_on=False) - if False: - cv2.imshow('clr_im', clr_im) - cv2.imshow('texmap', self.texture_image.r) - cv2.waitKey(1) - - r = clr_im[:,:,0].ravel()[IS] - g = clr_im[:,:,1].ravel()[IS] - b = clr_im[:,:,2].ravel()[IS] - data = np.concatenate((r,g,b)) + r = clr_im[:, :, 0].ravel()[IS] + g = clr_im[:, :, 1].ravel()[IS] + b = clr_im[:, :, 2].ravel()[IS] + data = np.concatenate((r, g, b)) IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) @@ -499,7 +490,7 @@ def compute_dr_wrt(self, wrt): return result - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ super(TexturedRenderer, self).on_changed(which) # have to redo if frustum changes, b/c frustum triggers new context @@ -522,16 +513,16 @@ def on_changed(self, which): @depends_on('vt', 'ft') def mesh_tex_coords(self): ftidxs = self.ft.ravel() - data = np.asarray(self.vt[ftidxs].astype(np.float32)[:,0:2], np.float32, order='C') - data[:,1] = 1.0 - 1.0*data[:,1] + data = np.asarray(self.vt[ftidxs].astype(np.float32)[:, 0:2], np.float32, order='C') + data[:, 1] = 1.0 - 1.0*data[:, 1] return data # Depends on 'f' because vpe/fpe depend on f @depends_on('vt', 'ft', 'f') def wireframe_tex_coords(self): - vvt = np.zeros((self.v.r.size/3,2), dtype=np.float32, order='C') + vvt = np.zeros((self.v.r.size/3, 2), dtype=np.float32, order='C') vvt[self.f.flatten()] = self.mesh_tex_coords - edata = np.zeros((self.vpe.size,2), dtype=np.float32, order='C') + edata = np.zeros((self.vpe.size, 2), dtype=np.float32, order='C') edata = vvt[self.vpe.ravel()] return edata @@ -539,7 +530,7 @@ def texture_mapping_on(self, gl, with_vertex_colors): gl.Enable(GL_TEXTURE_2D) gl.TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) gl.TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) - gl.TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE if with_vertex_colors else GL_REPLACE); + gl.TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE if with_vertex_colors else GL_REPLACE) gl.BindTexture(GL_TEXTURE_2D, self.textureID) gl.EnableClientState(GL_TEXTURE_COORD_ARRAY) @@ -562,35 +553,35 @@ def boundaryid_image(self): def boundarycolor_image(self): self._call_on_changed() gl = self.glf - colors = self.vc.r.reshape((-1,3))[self.vpe.ravel()] - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + colors = self.vc.r.reshape((-1, 3))[self.vpe.ravel()] + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.texture_mapping_on(gl, with_vertex_colors=False if colors is None else True) - gl.TexCoordPointerf(2,0, self.wireframe_tex_coords.ravel()) - draw_colored_primitives(self.glf, self.v.r.reshape((-1,3)), self.vpe, colors) + gl.TexCoordPointerf(2, 0, self.wireframe_tex_coords.ravel()) + draw_colored_primitives(self.glf, self.v.r.reshape((-1, 3)), self.vpe, colors) self.texture_mapping_off(gl) return np.asarray(deepcopy(gl.getImage()), np.float64) - def draw_color_image(self, with_vertex_colors=True, with_texture_on=True): + def draw_color_image(self, with_vertex_colors=True, with_texture_on=True): # pylint: disable=arguments-differ self._call_on_changed() gl = self.glf - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) if with_texture_on: self.texture_mapping_on(gl, with_vertex_colors) - gl.TexCoordPointerf(2,0, self.mesh_tex_coords.ravel()) + gl.TexCoordPointerf(2, 0, self.mesh_tex_coords.ravel()) else: self.texture_mapping_off(gl) colors = None if with_vertex_colors: - colors = self.vc.r.reshape((-1,3))[self.f.ravel()] - draw_colored_primitives(self.glf, self.v.r.reshape((-1,3)), self.f, colors) + colors = self.vc.r.reshape((-1, 3))[self.f.ravel()] + draw_colored_primitives(self.glf, self.v.r.reshape((-1, 3)), self.f, colors) self.texture_mapping_off(gl) - result = np.asarray(deepcopy(gl.getImage()), np.float64) + result = np.asarray(deepcopy(gl.getImage()), np.float64) if hasattr(self, 'background_image'): - bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1,1,3)) + bg_px = np.tile(np.atleast_3d(self.visibility_image) == 4294967295, (1, 1, 3)) fg_px = 1 - bg_px result = bg_px * self.background_image + fg_px * result @@ -599,10 +590,10 @@ def draw_color_image(self, with_vertex_colors=True, with_texture_on=True): @depends_on('vt', 'ft', 'f', 'frustum', 'camera') def texcoord_image_quantized(self): texcoord_image = self.texcoord_image.copy() - texcoord_image[:,:,0] *= self.texture_image.shape[1]-1 - texcoord_image[:,:,1] *= self.texture_image.shape[0]-1 + texcoord_image[:, :, 0] *= self.texture_image.shape[1]-1 + texcoord_image[:, :, 1] *= self.texture_image.shape[0]-1 texcoord_image = np.round(texcoord_image) - texcoord_image = texcoord_image[:,:,0] + texcoord_image[:,:,1]*self.texture_image.shape[1] + texcoord_image = texcoord_image[:, :, 0] + texcoord_image[:, :, 1]*self.texture_image.shape[1] return texcoord_image @@ -611,19 +602,19 @@ def texcoord_image(self): return draw_texcoord_image(self.glf, self.v.r, self.f, self.vt, self.ft, self.boundarybool_image if self.overdraw else None) # gl = self.glf # self.texture_mapping_off(gl) - # gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + # gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # - # # want vtc: texture-coordinates per vertex (not per element in vc) + # # want vtc: texture-coordinates per vertex(not per element in vc) # colors = self.vt[self.ft.ravel()] # #vtc = np.zeros((len(self.camera.r), 2)) # #for idx, vidx in enumerate(self.f.ravel()): # # tidx = self.ft.ravel()[idx] # # vtc[vidx] = self.vt[tidx] # - # colors = np.asarray(np.hstack((colors, col(colors[:,0]*0))), np.float64, order='C') - # draw_colored_primitives(gl, self.camera.r.reshape((-1,3)), self.f, colors) - # result = np.asarray(deepcopy(gl.getImage()), np.float64, order='C')[:,:,:2].copy() - # result[:,:,1] = 1. - result[:,:,1] + # colors = np.asarray(np.hstack((colors, col(colors[:, 0]*0))), np.float64, order='C') + # draw_colored_primitives(gl, self.camera.r.reshape((-1, 3)), self.f, colors) + # result = np.asarray(deepcopy(gl.getImage()), np.float64, order='C')[:, :, :2].copy() + # result[:, :, 1] = 1. - result[:, :, 1] # return result @@ -631,13 +622,13 @@ def texcoord_image(self): def draw_edge_visibility(gl, v, e, f, hidden_wireframe=True): """Assumes camera is set up correctly in gl context.""" - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ec = np.arange(1, len(e)+1) ec = np.tile(col(ec), (1, 3)) ec[:, 0] = ec[:, 0] & 255 - ec[:, 1] = (ec[:, 1] >> 8 ) & 255 - ec[:, 2] = (ec[:, 2] >> 16 ) & 255 + ec[:, 1] = (ec[:, 1] >> 8) & 255 + ec[:, 2] = (ec[:, 2] >> 16) & 255 ec = np.asarray(ec, dtype=np.uint8) draw_colored_primitives(gl, v, e, ec) @@ -649,90 +640,79 @@ def draw_edge_visibility(gl, v, e, f, hidden_wireframe=True): gl.Disable(GL_POLYGON_OFFSET_FILL) raw = np.asarray(gl.getImage(), np.uint32) - raw = raw[:,:,0] + raw[:,:,1]*256 + raw[:,:,2]*256*256 - 1 + raw = raw[:, :, 0] + raw[:, :, 1]*256 + raw[:, :, 2]*256*256 - 1 return raw def draw_boundary_images(glf, glb, v, f, vpe, fpe, camera): """Assumes camera is set up correctly, and that glf has any texmapping on necessary.""" - glf.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glb.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glf.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + glb.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Figure out which edges are on pairs of differently visible triangles from opendr.geometry import TriNormals - tn = TriNormals(v, f).r.reshape((-1,3)) + tn = TriNormals(v, f).r.reshape((-1, 3)) campos = -cv2.Rodrigues(camera.rt.r)[0].T.dot(camera.t.r) - rays_to_verts = v.reshape((-1,3)) - row(campos) - rays_to_faces = rays_to_verts[f[:,0]] + rays_to_verts[f[:,1]] + rays_to_verts[f[:,2]] + rays_to_verts = v.reshape((-1, 3)) - row(campos) + rays_to_faces = rays_to_verts[f[:, 0]] + rays_to_verts[f[:, 1]] + rays_to_verts[f[:, 2]] dps = np.sum(rays_to_faces * tn, axis=1) - dps = dps[fpe[:,0]] * dps[fpe[:,1]] - silhouette_edges = np.asarray(np.nonzero(dps<=0)[0], np.uint32) - non_silhouette_edges = np.nonzero(dps>0)[0] + dps = dps[fpe[:, 0]] * dps[fpe[:, 1]] + silhouette_edges = np.asarray(np.nonzero(dps <= 0)[0], np.uint32) lines_e = vpe[silhouette_edges] lines_v = v visibility = draw_edge_visibility(glb, lines_v, lines_e, f, hidden_wireframe=True) - shape = visibility.shape + visibility_shape = visibility.shape visibility = visibility.ravel() visible = np.nonzero(visibility.ravel() != 4294967295)[0] visibility[visible] = silhouette_edges[visibility[visible]] - result = visibility.reshape(shape) + result = visibility.reshape(visibility_shape) return result def compute_vpe_boundary_idxs(v, f, camera, fpe): # Figure out which edges are on pairs of differently visible triangles - from geometry import TriNormals - tn = TriNormals(v, f).r.reshape((-1,3)) + from opendr.geometry import TriNormals + tn = TriNormals(v, f).r.reshape((-1, 3)) - #ray = cv2.Rodrigues(camera.rt.r)[0].T[:,2] + #ray = cv2.Rodrigues(camera.rt.r)[0].T[:, 2] campos = -cv2.Rodrigues(camera.rt.r)[0].T.dot(camera.t.r) - rays_to_verts = v.reshape((-1,3)) - row(campos) - rays_to_faces = rays_to_verts[f[:,0]] + rays_to_verts[f[:,1]] + rays_to_verts[f[:,2]] + rays_to_verts = v.reshape((-1, 3)) - row(campos) + rays_to_faces = rays_to_verts[f[:, 0]] + rays_to_verts[f[:, 1]] + rays_to_verts[f[:, 2]] faces_invisible = np.sum(rays_to_faces * tn, axis=1) - dps = faces_invisible[fpe[:,0]] * faces_invisible[fpe[:,1]] - silhouette_edges = np.asarray(np.nonzero(dps<=0)[0], np.uint32) + dps = faces_invisible[fpe[:, 0]] * faces_invisible[fpe[:, 1]] + silhouette_edges = np.asarray(np.nonzero(dps <= 0)[0], np.uint32) return silhouette_edges, faces_invisible < 0 def draw_boundaryid_image(gl, v, f, vpe, fpe, camera, x0=None, x1=None, y0=None, y1=None): + # visibility = draw_edge_visibility(gl, v, vpe, f, hidden_wireframe=True) + # return visibility + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) - if False: - visibility = draw_edge_visibility(gl, v, vpe, f, hidden_wireframe=True) - return visibility - - if True: - #try: - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - silhouette_edges, faces_facing_camera = compute_vpe_boundary_idxs(v, f, camera, fpe) - lines_e = vpe[silhouette_edges] - lines_v = v - - if len(lines_e)==0: - return np.ones((gl.height, gl.width)).astype(np.int32) * 4294967295 - visibility = draw_edge_visibility(gl, lines_v, lines_e, f, hidden_wireframe=True) - - # Crop - if x0 != None and isinstance(x0, int): - visibility[:y0] = -1 - visibility[y1:] = -1 - visibility[y0:y1, :x0] = -1 - visibility[y0:y1, x1:] = -1 + silhouette_edges, _ = compute_vpe_boundary_idxs(v, f, camera, fpe) + lines_e = vpe[silhouette_edges] + lines_v = v - shape = visibility.shape - visibility = visibility.ravel() - visible = np.nonzero(visibility.ravel() != 4294967295)[0] - visibility[visible] = silhouette_edges[visibility[visible]] - result = visibility.reshape(shape) - return result + if len(lines_e) == 0: + return np.ones((gl.height, gl.width)).astype(np.int32) * 4294967295 + visibility = draw_edge_visibility(gl, lines_v, lines_e, f, hidden_wireframe=True) - #return np.asarray(deepcopy(gl.getImage()), np.float64) - #except: - # import pdb; pdb.set_trace() + # Crop + if x0 != None and isinstance(x0, int): + visibility[:y0] = -1 + visibility[y1:] = -1 + visibility[y0:y1, :x0] = -1 + visibility[y0:y1, x1:] = -1 + visibility_shape = visibility.shape + visibility = visibility.ravel() + visible = np.nonzero(visibility.ravel() != 4294967295)[0] + visibility[visible] = silhouette_edges[visibility[visible]] + result = visibility.reshape(visibility_shape) + return result def setup_camera(gl, camera, frustum): @@ -829,17 +809,17 @@ def setup_camera(gl, camera, frustum): def _setup_camera(gl, cx, cy, fx, fy, w, h, near, far, view_matrix, k): k = np.asarray(k) gl.MatrixMode(GL_PROJECTION) - gl.LoadIdentity(); + gl.LoadIdentity() f = 0.5 * (fx + fy) - right = (w-(cx+pixel_center_offset)) * (near/f) - left = -(cx+pixel_center_offset) * (near/f) - top = -(h-(cy+pixel_center_offset)) * (near/f) - bottom = (cy+pixel_center_offset) * (near/f) + right = (w-(cx+pixel_center_offset)) * (near/f) + left = -(cx+pixel_center_offset) * (near/f) + top = -(h-(cy+pixel_center_offset)) * (near/f) + bottom = (cy+pixel_center_offset) * (near/f) gl.Frustum(left, right, bottom, top, near, far) - gl.MatrixMode(GL_MODELVIEW); - gl.LoadIdentity(); # I + gl.MatrixMode(GL_MODELVIEW) + gl.LoadIdentity() # I gl.Rotatef(180, 1, 0, 0) # I * xR(pi) view_mtx = np.asarray(np.vstack((view_matrix, np.array([0, 0, 0, 1]))), np.float32, order='F') @@ -849,8 +829,8 @@ def _setup_camera(gl, cx, cy, fx, fy, w, h, near, far, view_matrix, k): gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL) gl.Disable(GL_LIGHTING) gl.Disable(GL_CULL_FACE) - gl.PixelStorei(GL_PACK_ALIGNMENT,1) - gl.PixelStorei(GL_UNPACK_ALIGNMENT,1) + gl.PixelStorei(GL_PACK_ALIGNMENT, 1) + gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1) if np.any(k): if not hasattr(gl, 'distortion_shader'): @@ -884,23 +864,16 @@ def _setup_camera(gl, cx, cy, fx, fy, w, h, near, far, view_matrix, k): def draw_colored_verts(gl, v, f, vc): # TODO: copying is inefficient here if vc.shape[1] != 3: - vc = np.vstack((vc[:,0], vc[:,1%vc.shape[1]], vc[:,2%vc.shape[1]])).T.copy() - assert(vc.shape[1]==3) - gl.EnableClientState(GL_VERTEX_ARRAY); - gl.EnableClientState(GL_COLOR_ARRAY); - gl.VertexPointer(np.ascontiguousarray(v).reshape((-1,3))); - gl.ColorPointerd(np.ascontiguousarray(vc).reshape((-1,3))); + vc = np.vstack((vc[:, 0], vc[:, 1%vc.shape[1]], vc[:, 2%vc.shape[1]])).T.copy() + assert vc.shape[1] == 3 + gl.EnableClientState(GL_VERTEX_ARRAY) + gl.EnableClientState(GL_COLOR_ARRAY) + gl.VertexPointer(np.ascontiguousarray(v).reshape((-1, 3))) + gl.ColorPointerd(np.ascontiguousarray(vc).reshape((-1, 3))) gl.DrawElements(GL_TRIANGLES, np.asarray(f, np.uint32).ravel()) def draw_noncolored_verts(gl, v, f): - gl.EnableClientState(GL_VERTEX_ARRAY); - gl.DisableClientState(GL_COLOR_ARRAY); - gl.VertexPointer(np.ascontiguousarray(v).reshape((-1,3))); + gl.EnableClientState(GL_VERTEX_ARRAY) + gl.DisableClientState(GL_COLOR_ARRAY) + gl.VertexPointer(np.ascontiguousarray(v).reshape((-1, 3))) gl.DrawElements(GL_TRIANGLES, np.asarray(f, np.uint32).ravel()) - -def main(): - pass - -if __name__ == '__main__': - main() - diff --git a/opendr/rogrenderer.py b/opendr/rogrenderer.py index b8ab683..0242d9e 100644 --- a/opendr/rogrenderer.py +++ b/opendr/rogrenderer.py @@ -22,10 +22,10 @@ def draw_color_image(self, with_vertex_colors): return self.compute_rog(result) def compute_rog(self, im, is_real=False): - if (self.sigma_small>=self.sigma_big) or (self.sigma_small==0): return im + if(self.sigma_small >= self.sigma_big) or(self.sigma_small == 0): return im if self.frustum['height'] != np.shape(im)[0]: - im = cv2.resize(im, (self.frustum['width'], self.frustum['height'] )) - if (len(im.shape)==3): im = np.mean(im, axis=2) + im = cv2.resize(im, (self.frustum['width'], self.frustum['height'])) + if(len(im.shape) == 3): im = np.mean(im, axis=2) im = np.asarray(im, np.float64)/255. visibility = super(self.__class__, self).visibility_image @@ -56,16 +56,16 @@ def compute_rog(self, im, is_real=False): np.random.seed(0) camera = get_camera(scaling=.4) camera, frustum = convertCam(camera) - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation = np.array([0, 0, 0])) lighting = LambertianPointLight( f=mesh.f, num_verts=len(mesh.v), - light_pos=np.array([-1000,-1000,-1000]), + light_pos=np.array([-1000, -1000, -1000]), vc=mesh.vc, light_color=np.array([1., 1., 1.])) - bgcolor = np.array([0.,0.,0.]) + bgcolor = np.array([0., 0., 0.]) renderers = [ TexturedRenderer(f=mesh.f, vc=mesh.vc, v=mesh.v, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor), RogTexRenderer(f=mesh.f, vc=mesh.vc, v=mesh.v, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor, sigma_small=3, sigma_big=5)] diff --git a/opendr/serialization.py b/opendr/serialization.py index 8b51a5d..cd05db9 100644 --- a/opendr/serialization.py +++ b/opendr/serialization.py @@ -15,7 +15,7 @@ def load_image(filename): - return (cv2.imread(filename)[:,:,::-1]/255.).copy() + return(cv2.imread(filename)[:, :, ::-1]/255.).copy() def load_mesh(filename): @@ -25,7 +25,7 @@ def load_mesh(filename): elif extension == '.obj': return read_obj(filename) else: - raise Exception('Unsupported file extension for %s' % (filename,)) + raise Exception('Unsupported file extension for %s' % (filename, )) def _update_mtl(mtl, filename): @@ -96,7 +96,7 @@ def read_obj(filename): if not exists(dst_fname): dst_fname = src_fname if not exists(dst_fname): - raise Exception("Unable to find referenced texture map %s" % (src_fname,)) + raise Exception("Unable to find referenced texture map %s" % (src_fname, )) else: d['texture_filepath'] = normpath(dst_fname) im = cv2.imread(dst_fname) @@ -105,7 +105,7 @@ def read_obj(filename): d['texture_image'] = cv2.resize(im, (sz, sz)).astype(np.float64)/255. for k, v in d.items(): - if k in ['v','vn','f','vt','ft']: + if k in ['v', 'vn', 'f', 'vt', 'ft']: if v: d[k] = np.vstack(v) else: diff --git a/opendr/slider_demo.py b/opendr/slider_demo.py index 72a61b1..a41630c 100644 --- a/opendr/slider_demo.py +++ b/opendr/slider_demo.py @@ -13,23 +13,23 @@ def get_renderer(): # Load mesh m = load_mesh('/Users/matt/geist/OpenDR/test_dr/nasa_earth.obj') - m.v += ch.array([0,0,3.]) + m.v += ch.array([0, 0, 3.]) w, h = (320, 240) - trans = ch.array([[0,0,0]]) + trans = ch.array([[0, 0, 0]]) # Construct renderer rn = TexturedRenderer() - rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) + rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} - rn.set(v=trans+m.v, f=m.f, texture_image=m.texture_image[:,:,::-1], ft=m.ft, vt=m.vt, bgcolor=ch.zeros(3)) - rn.vc = SphericalHarmonics(vn=VertNormals(v=rn.v, f=rn.f), components=ch.array([4.,0.,0.,0.]), light_color=ch.ones(3)) + rn.set(v=trans+m.v, f=m.f, texture_image=m.texture_image[:, :, ::-1], ft=m.ft, vt=m.vt, bgcolor=ch.zeros(3)) + rn.vc = SphericalHarmonics(vn=VertNormals(v=rn.v, f=rn.f), components=ch.array([4., 0., 0., 0.]), light_color=ch.ones(3)) return rn def main(): # Create a black image, a window - img = np.zeros((300,512,3), np.uint8) + img = np.zeros((300, 512, 3), np.uint8) cv2.namedWindow('image') cv2.namedWindow('derivatives') @@ -48,12 +48,12 @@ def main(): cnst = 1000 for k in sorted(tracked.keys()): v = tracked[k] - cv2.createTrackbar(k, 'image', 0,cnst, nothing) + cv2.createTrackbar(k, 'image', 0, cnst, nothing) old_tracked = tracked cv2.setTrackbarPos('sph0', 'image', 800) while(1): - cv2.imshow('image',rn.r) + cv2.imshow('image', rn.r) k = cv2.waitKey(1) & 0xFF if k == 27: break @@ -77,7 +77,7 @@ def main(): # continue # for t in np.arange(0, np.pi, .05): # cv2.setTrackbarPos(k_change, 'image', int(np.sin(t)*1000)) - # cv2.imshow('image',rn.r) + # cv2.imshow('image', rn.r) # k = cv2.waitKey(1) & 0xFF # if k == 27: # break diff --git a/opendr/test_camera.py b/opendr/test_camera.py index b5f8ac8..8c5efc4 100755 --- a/opendr/test_camera.py +++ b/opendr/test_camera.py @@ -19,13 +19,13 @@ class TestCamera(unittest.TestCase): def get_cam_params(self): - v_raw = np.sin(np.arange(900)).reshape((-1,3)) + v_raw = np.sin(np.arange(900)).reshape((-1, 3)) v_raw[:, 2] -= 2 rt = ch.zeros(3) t = ch.zeros(3) - f = ch.array([500,500]) - c = ch.array([320,240]) + f = ch.array([500, 500]) + c = ch.array([320, 240]) k = ch.zeros(5) cam_params = {'v': ch.Ch(v_raw), 'rt': rt, 't': t, 'f': f, 'c': c, 'k': k} @@ -34,7 +34,7 @@ def get_cam_params(self): def test_project_points_without_derivatives(self): from util_tests import get_earthmesh cam_params = self.get_cam_params() - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation = np.array([0, 0, 0])) pp = ProjectPoints(f=cam_params['f'], rt=cam_params['rt'], t=cam_params['t'], k=cam_params['k'], c=cam_params['c']) pp.v = mesh.v @@ -68,12 +68,12 @@ def project_points(self, cls): max_diff = np.max(raw_dr_diff) #pct_diff = (100. * max_diff / np.mean(np.abs(old_val.flatten()))) - # print 'testing for %s' % (key,) + # print 'testing for %s' % (key, ) # print 'empirical' + str(diff.flatten()[:5]) # print 'predicted' + str(old_dr[:5]) - # print 'med diff: %.2e' % (med_diff,) - # print 'max diff: %.2e' % (max_diff,) - #print 'pct diff: %.2e%%' % (pct_diff,) + # print 'med diff: %.2e' % (med_diff, ) + # print 'max diff: %.2e' % (max_diff, ) + #print 'pct diff: %.2e%%' % (pct_diff, ) self.assertLess(med_diff, 1e-8) self.assertLess(max_diff, 5e-8) @@ -82,12 +82,12 @@ def project_points(self, cls): pp_dist = cls(**cam_params) # Test to make sure that depends_on is working - for name in ('rt', 't', 'f', 'c', 'k'): + for name in('rt', 't', 'f', 'c', 'k'): aa = pp_dist.camera_mtx setattr(pp_dist, name, getattr(pp_dist, name).r + 1) bb = pp_dist.camera_mtx - if name in ('f', 'c'): + if name in('f', 'c'): self.assertTrue(aa is not bb) else: self.assertTrue(aa is bb) diff --git a/opendr/test_depth_renderer.py b/opendr/test_depth_renderer.py index ee02e7c..4e0fe00 100644 --- a/opendr/test_depth_renderer.py +++ b/opendr/test_depth_renderer.py @@ -18,12 +18,12 @@ def test_depth_image(self): # Assign attributes to renderer from util_tests import get_earthmesh - m = get_earthmesh(trans=ch.array([0,0,0]), rotation=ch.zeros(3)) + m = get_earthmesh(trans=ch.array([0, 0, 0]), rotation=ch.zeros(3)) m.v = m.v * .01 - m.v[:,2] += 4 + m.v[:, 2] += 4 w, h = (320, 240) from camera import ProjectPoints - rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) + rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3)) @@ -35,8 +35,8 @@ def test_depth_image(self): # print np.min(rn.r.ravel()) # print np.max(rn.r.ravel()) self.assertLess(np.abs(np.min(rn.r.ravel()) - 3.98), 1e-5) - self.assertLess(np.abs(np.min(m.v[:,2]) - np.min(rn.r.ravel())), 1e-5) - self.assertLess(np.abs(rn.r[h/2,w/2] - 3.98), 1e-5) + self.assertLess(np.abs(np.min(m.v[:, 2]) - np.min(rn.r.ravel())), 1e-5) + self.assertLess(np.abs(rn.r[h/2, w/2] - 3.98), 1e-5) def test_derivatives(self): import chumpy as ch @@ -48,10 +48,10 @@ def test_derivatives(self): # Assign attributes to renderer from util_tests import get_earthmesh - m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) + m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from camera import ProjectPoints - rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) + rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) @@ -75,13 +75,13 @@ def test_derivatives(self): self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .031) if visualize: - plt.subplot(2,3,which+1) + plt.subplot(2, 3, which+1) plt.imshow(dr_pred) - plt.clim(-.01,.01) + plt.clim(-.01, .01) plt.title('emp') - plt.subplot(2,3,which+4) + plt.subplot(2, 3, which+4) plt.imshow(dr_emp) - plt.clim(-.01,.01) + plt.clim(-.01, .01) plt.title('pred') def test_derivatives2(self): @@ -93,10 +93,10 @@ def test_derivatives2(self): # Assign attributes to renderer from util_tests import get_earthmesh - m = get_earthmesh(trans=ch.array([0,0,4]), rotation=ch.zeros(3)) + m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) from camera import ProjectPoints - rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w,w])/2., c=ch.array([w,h])/2., k=ch.zeros(5)) + rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) @@ -121,13 +121,13 @@ def test_derivatives2(self): self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .024) if visualize: - plt.subplot(2,3,which+1) + plt.subplot(2, 3, which+1) plt.imshow(dr_pred) - plt.clim(-.01,.01) + plt.clim(-.01, .01) plt.title('emp') - plt.subplot(2,3,which+4) + plt.subplot(2, 3, which+4) plt.imshow(dr_emp) - plt.clim(-.01,.01) + plt.clim(-.01, .01) plt.title('pred') plt.draw() plt.show() diff --git a/opendr/test_geometry.py b/opendr/test_geometry.py index a95c10d..b9a3887 100755 --- a/opendr/test_geometry.py +++ b/opendr/test_geometry.py @@ -6,13 +6,9 @@ See LICENCE.txt for licensing and contact information. """ -import sys -import os import unittest -import chumpy as ch -from chumpy import Ch import numpy as np -from util_tests import get_earthmesh +from opendr.util_tests import get_earthmesh class TestGeometry(unittest.TestCase): @@ -20,21 +16,20 @@ def setUp(self): np.random.seed(0) def test_rodrigues(self): - from geometry import Rodrigues + from opendr.geometry import Rodrigues rt = np.random.randn(3) rt2 = rt + np.random.rand(3)*1e-5 - foo1 = Rodrigues(rt = rt) - foo2 = Rodrigues(rt = rt2) + foo1 = Rodrigues(rt=rt) + foo2 = Rodrigues(rt=rt2) empirical = (foo2.r - foo1.r).flatten() predicted = foo1.dr_wrt(foo1.rt).dot(rt2-rt) - self.assertTrue(np.max(np.abs(empirical - predicted)) < 1e-10) + self.assertLess(np.max(np.abs(empirical - predicted)), 1e-10) def test_vert_normals(self): - from geometry import VertNormals - import numpy as np + from opendr.geometry import VertNormals mesh = get_earthmesh(np.zeros(3), np.zeros(3)) v, f = mesh.v*127., mesh.f @@ -45,19 +40,11 @@ def test_vert_normals(self): eps = .00001 * np.random.randn(v.size).reshape(v.shape) v += eps vn2 = VertNormals(v=v, f=f) - empirical_diff = (vn2.r - vn1.r).reshape((-1,3)) + empirical_diff = (vn2.r - vn1.r).reshape((-1, 3)) - predicted_diff = dr_predicted.dot(eps.flatten()).reshape((-1,3)) + predicted_diff = dr_predicted.dot(eps.flatten()).reshape((-1, 3)) - if False: - print np.max(np.abs(empirical_diff-predicted_diff)) - print empirical_diff[:6] - print predicted_diff[:6] - self.assertTrue(np.max(np.abs(empirical_diff-predicted_diff)) < 6e-13) - - - -suite = unittest.TestLoader().loadTestsFromTestCase(TestGeometry) - -if __name__ == '__main__': - unittest.main() + # print np.max(np.abs(empirical_diff-predicted_diff)) + # print empirical_diff[:6] + # print predicted_diff[:6] + self.assertLess(np.max(np.abs(empirical_diff-predicted_diff)), 6e-13) diff --git a/opendr/test_renderer.py b/opendr/test_renderer.py index b8629e6..a98598b 100755 --- a/opendr/test_renderer.py +++ b/opendr/test_renderer.py @@ -6,46 +6,40 @@ See LICENCE.txt for licensing and contact information. """ -import time import math import unittest +from collections import OrderedDict import numpy as np -import unittest +from chumpy import Ch +from chumpy.utils import col try: import matplotlib.pyplot as plt import matplotlib -except: - from dummy import dummy as plt +except ImportError: + from opendr.dummy import dummy as plt +from opendr.renderer import ColoredRenderer, TexturedRenderer +from opendr.lighting import LambertianPointLight +from opendr.cvwrap import cv2 +from opendr.util_tests import get_earthmesh, process -from renderer import * # pylint: disable=wildcard-import, unused-wildcard-import -from chumpy import Ch -from chumpy.utils import row, col -from lighting import * -from util_tests import get_earthmesh, process -from collections import OrderedDict - - - -visualize = False def getcam(): - from camera import ProjectPoints + from opendr.camera import ProjectPoints w = 256 h = 192 - f = np.array([200.,200.]) + f = np.array([200., 200.]) rt = np.zeros(3) t = np.zeros(3) k = np.zeros(5) c = np.array([w/2., h/2.]) - if True: - ratio = 640 / 256. - f *= ratio - c *= ratio - w *= ratio - h *= ratio + ratio = 640 / 256. + f *= ratio + c *= ratio + w *= ratio + h *= ratio pp = ProjectPoints(f=f, rt=rt, t=t, k=k, c=c) frustum = {'near': 1.0, 'far': 20.0, 'width': w, 'height': h} @@ -53,26 +47,27 @@ def getcam(): return pp, frustum class TestRenderer(unittest.TestCase): + VISUALIZE = False def load_basics(self): np.random.seed(0) camera, frustum = getcam() - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([0,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([0, 0, 0])) lighting_3channel = LambertianPointLight( f=mesh.f, num_verts=len(mesh.v), - light_pos=np.array([-1000,-1000,-1000]), + light_pos=np.array([-1000, -1000, -1000]), vc=mesh.vc, light_color=np.array([1., 1., 1.])) lighting_1channel = LambertianPointLight( f=mesh.f, num_verts=len(mesh.v), - light_pos=np.array([-1000,-1000,-1000]), - vc=mesh.vc.mean(axis=1).reshape((-1,1)), + light_pos=np.array([-1000, -1000, -1000]), + vc=mesh.vc.mean(axis=1).reshape((-1, 1)), light_color=np.array([1.])) - bgcolor = np.array([0.,0.,0.]) + bgcolor = np.array([0., 0., 0.]) renderers = [ ColoredRenderer(f=mesh.f, camera=camera, frustum=frustum, bgcolor=bgcolor, num_channels=3), TexturedRenderer(f=mesh.f, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor), @@ -83,8 +78,8 @@ def load_basics(self): def test_pyramids(self): """ Test that pyramid construction doesn't crash. No quality testing here. """ - mesh, lightings, camera, frustum, renderers = self.load_basics() - from filters import gaussian_pyramid, laplacian_pyramid, GaussPyrDownOne + mesh, lightings, camera, _, renderers = self.load_basics() + from opendr.filters import gaussian_pyramid, laplacian_pyramid, GaussPyrDownOne camera.v = mesh.v for rn in renderers: @@ -97,21 +92,18 @@ def test_pyramids(self): _ = rn_lap.r _ = rn_gpr.r for r in [rn_pyr, rn_gpr]: - for ii in range(3): - rn.v[:,:] = rn.v[:,:].r + 1e-10 - import time - tm = time.time() + for _ in range(3): + rn.v[:, :] = rn.v[:, :].r + 1e-10 _ = r.dr_wrt(rn) - #print "trial %d: %.2fS " % (ii, time.time() - tm) def test_distortion(self): - mesh, lightings, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, _, renderers = self.load_basics() renderer = renderers[1] lighting = lightings[renderer.num_channels] lighting.light_pos = -lighting.light_pos * 100. - mesh = get_earthmesh(trans=np.array([0,0,-8]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, -8]), rotation=np.array([math.pi/2., 0, 0])) mesh_verts = Ch(mesh.v.flatten()) renderer.camera = camera camera.v = mesh_verts @@ -125,9 +117,9 @@ def test_distortion(self): im_original = renderer.r.copy() #camera.k = np.zeros(5) - #camera.k = np.arange(8,0,-1)*.1 + #camera.k = np.arange(8, 0, -1)*.1 #camera.k = np.array([ 0.00249999, 0.42208098, 0.45360267, 0.06808415, -0.38003062]) - camera.k = np.array([ 5., 25., .3, .4, 1000., 5., 0., 0.]) + camera.k = np.array([5., 25., .3, .4, 1000., 5., 0., 0.]) im_distorted = renderer.r cr = renderer @@ -137,7 +129,6 @@ def test_distortion(self): [0, 0, 1] ]) - from cvwrap import cv2 im_undistorted = cv2.undistort(im_distorted, cmtx, cr.camera.k.r) d1 = (im_original - im_distorted).ravel() @@ -152,25 +143,24 @@ def test_distortion(self): self.assertLess(np.median(d2**2), 1.9e-5) - if visualize: - import matplotlib.pyplot as plt + if self.VISUALIZE: plt.ion() matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) - plt.subplot(1,4,1) + plt.subplot(1, 4, 1) plt.imshow(im_original) plt.title('original') - plt.subplot(1,4,2) + plt.subplot(1, 4, 2) plt.imshow(im_distorted) plt.title('distorted') - plt.subplot(1,4,3) + plt.subplot(1, 4, 3) plt.imshow(im_undistorted) plt.title('undistorted by opencv') - plt.subplot(1,4,4) + plt.subplot(1, 4, 4) plt.imshow(im_undistorted - im_original + .5) plt.title('diff') @@ -183,7 +173,7 @@ def test_distortion(self): def test_cam_derivatives(self): - mesh, lightings, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, _, renderers = self.load_basics() camparms = { 'c': {'mednz' : 2.2e-2, 'meannz': 4.3e-2, 'desc': 'center of proj diff', 'eps0': 4., 'eps1': .1}, @@ -199,7 +189,7 @@ def test_cam_derivatives(self): lighting = lightings[renderer.num_channels] # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([math.pi/2., 0, 0])) mesh_verts = Ch(mesh.v.flatten()) camera.v = mesh_verts lighting.v = mesh_verts @@ -210,12 +200,12 @@ def test_cam_derivatives(self): for atrname, info in camparms.items(): # Get pixels and derivatives - r = renderer.r + _ = renderer.r - atr = lambda : getattr(camera, atrname) - satr = lambda x : setattr(camera, atrname, x) + atr = lambda: getattr(camera, atrname) # fine because the closure is only used inside the loop pylint: disable=cell-var-from-loop + satr = lambda x: setattr(camera, atrname, x) # same pylint: disable=cell-var-from-loop - atr_size = atr().size + # atr_size = atr().size dr = renderer.dr_wrt(atr()) # Establish a random direction @@ -245,26 +235,26 @@ def test_cam_derivatives(self): dr_predicted = dr.dot(col(direction.flatten())).reshape(dr_empirical.shape) images = OrderedDict() - images['shifted %s' % (atrname,)] = np.asarray(rfwd, np.float64)-.5 - images[r'empirical %s' % (atrname,)] = dr_empirical - images[r'predicted %s' % (atrname,)] = dr_predicted + images['shifted %s' % (atrname, )] = np.asarray(rfwd, np.float64)-.5 + images[r'empirical %s' % (atrname, )] = dr_empirical + images[r'predicted %s' % (atrname, )] = dr_predicted images[info['desc']] = dr_predicted - dr_empirical - nonzero = images[info['desc']][np.nonzero(images[info['desc']]!=0)[0]] + nonzero = images[info['desc']][np.nonzero(images[info['desc']] != 0)[0]] mederror = np.median(np.abs(nonzero)) meanerror = np.mean(np.abs(nonzero)) - if visualize: + if self.VISUALIZE: matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) for idx, title in enumerate(images.keys()): - plt.subplot(1,len(images.keys()), idx+1) + plt.subplot(1, len(images.keys()), idx+1) im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) - print '%s: median nonzero %.2e' % (atrname, mederror,) - print '%s: mean nonzero %.2e' % (atrname, meanerror,) + print '%s: median nonzero %.2e' % (atrname, mederror, ) + print '%s: mean nonzero %.2e' % (atrname, meanerror, ) plt.draw() plt.show() @@ -274,7 +264,7 @@ def test_cam_derivatives(self): def test_vert_derivatives(self): - mesh, lightings, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, _, renderers = self.load_basics() for renderer in renderers: @@ -282,7 +272,7 @@ def test_vert_derivatives(self): im_shape = renderer.shape # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([math.pi/2., 0, 0])) mesh_verts = Ch(mesh.v.flatten()) camera.set(v=mesh_verts) lighting.set(v=mesh_verts) @@ -290,7 +280,7 @@ def test_vert_derivatives(self): renderer.set(vc=lighting) # Get pixels and derivatives - r = renderer.r + _ = renderer.r dr = renderer.dr_wrt(mesh_verts) # Establish a random direction @@ -320,19 +310,19 @@ def test_vert_derivatives(self): images[r'predicted verts $\left(\frac{dI}{dV}\right)$'] = dr_predicted images['difference verts'] = dr_predicted - dr_empirical - nonzero = images['difference verts'][np.nonzero(images['difference verts']!=0)[0]] + nonzero = images['difference verts'][np.nonzero(images['difference verts'] != 0)[0]] - if visualize: + if self.VISUALIZE: matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) for idx, title in enumerate(images.keys()): - plt.subplot(1,len(images.keys()), idx+1) + plt.subplot(1, len(images.keys()), idx+1) im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) - print 'verts: median nonzero %.2e' % (np.median(np.abs(nonzero)),) - print 'verts: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) + print 'verts: median nonzero %.2e' % (np.median(np.abs(nonzero)), ) + print 'verts: mean nonzero %.2e' % (np.mean(np.abs(nonzero)), ) plt.draw() plt.show() @@ -342,7 +332,7 @@ def test_vert_derivatives(self): def test_lightpos_derivatives(self): - mesh, lightings, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, _, renderers = self.load_basics() for renderer in renderers: @@ -351,13 +341,13 @@ def test_lightpos_derivatives(self): lighting = lightings[renderer.num_channels] # Render a rotating mesh - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([math.pi/2., 0, 0])) mesh_verts = Ch(mesh.v.flatten()) camera.set(v=mesh_verts) # Get predicted derivatives wrt light pos - light1_pos = Ch(np.array([-1000,-1000,-1000])) + light1_pos = Ch(np.array([-1000, -1000, -1000])) lighting.set(light_pos=light1_pos, v=mesh_verts) renderer.set(vc=lighting, v=mesh_verts) @@ -368,12 +358,12 @@ def test_lightpos_derivatives(self): eps = 1. # Find empirical forward derivatives in that direction - lighting.set(light_pos = light1_pos.r + direction*eps/2.) + lighting.set(light_pos=light1_pos.r + direction*eps/2.) renderer.set(vc=lighting) rfwd = renderer.r # Find empirical backward derivatives in that direction - lighting.set(light_pos = light1_pos.r - direction*eps/2.) + lighting.set(light_pos=light1_pos.r - direction*eps/2.) renderer.set(vc=lighting) rbwd = renderer.r @@ -387,20 +377,20 @@ def test_lightpos_derivatives(self): images[r'predicted lightpos $\left(\frac{dI}{dL_p}\right)$'] = dr_predicted images['difference lightpos'] = dr_predicted-dr_empirical - nonzero = images['difference lightpos'][np.nonzero(images['difference lightpos']!=0)[0]] + nonzero = images['difference lightpos'][np.nonzero(images['difference lightpos'] != 0)[0]] - if visualize: + if self.VISUALIZE: matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) for idx, title in enumerate(images.keys()): - plt.subplot(1,len(images.keys()), idx+1) + plt.subplot(1, len(images.keys()), idx+1) im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) plt.show() - print 'lightpos: median nonzero %.2e' % (np.median(np.abs(nonzero)),) - print 'lightpos: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) + print 'lightpos: median nonzero %.2e' % (np.median(np.abs(nonzero)), ) + print 'lightpos: mean nonzero %.2e' % (np.mean(np.abs(nonzero)), ) self.assertLess(np.mean(np.abs(nonzero)), 2.4e-2) self.assertLess(np.median(np.abs(nonzero)), 1.2e-2) @@ -408,7 +398,7 @@ def test_lightpos_derivatives(self): def test_color_derivatives(self): - mesh, lightings, camera, frustum, renderers = self.load_basics() + mesh, lightings, camera, _, renderers = self.load_basics() for renderer in renderers: @@ -416,7 +406,7 @@ def test_color_derivatives(self): lighting = lightings[renderer.num_channels] # Get pixels and dI/dC - mesh = get_earthmesh(trans=np.array([0,0,5]), rotation = np.array([math.pi/2.,0,0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([math.pi/2., 0, 0])) mesh_verts = Ch(mesh.v) mesh_colors = Ch(mesh.vc) @@ -426,12 +416,12 @@ def test_color_derivatives(self): # print '-------------------------------------------' #lighting.set(vc=mesh_colors, v=mesh_verts) - lighting.vc = mesh_colors[:,:renderer.num_channels] + lighting.vc = mesh_colors[:, :renderer.num_channels] lighting.v = mesh_verts renderer.set(v=mesh_verts, vc=lighting) - r = renderer.r + _ = renderer.r dr = renderer.dr_wrt(mesh_colors).copy() # Establish a random direction @@ -440,13 +430,13 @@ def test_color_derivatives(self): # Find empirical forward derivatives in that direction mesh_colors = Ch(mesh.vc+direction.reshape(mesh.vc.shape)*eps/2.) - lighting.set(vc=mesh_colors[:,:renderer.num_channels]) + lighting.set(vc=mesh_colors[:, :renderer.num_channels]) renderer.set(vc=lighting) rfwd = renderer.r # Find empirical backward derivatives in that direction mesh_colors = Ch(mesh.vc-direction.reshape(mesh.vc.shape)*eps/2.) - lighting.set(vc=mesh_colors[:,:renderer.num_channels]) + lighting.set(vc=mesh_colors[:, :renderer.num_channels]) renderer.set(vc=lighting) rbwd = renderer.r @@ -459,20 +449,20 @@ def test_color_derivatives(self): images[r'predicted colors $\left(\frac{dI}{dC}\right)$'] = dr_predicted images['difference colors'] = dr_predicted-dr_empirical - nonzero = images['difference colors'][np.nonzero(images['difference colors']!=0)[0]] + nonzero = images['difference colors'][np.nonzero(images['difference colors'] != 0)[0]] - if visualize: + if self.VISUALIZE: matplotlib.rcParams.update({'font.size': 18}) plt.figure(figsize=(6*3, 2*3)) for idx, title in enumerate(images.keys()): - plt.subplot(1,len(images.keys()), idx+1) + plt.subplot(1, len(images.keys()), idx+1) im = process(images[title].reshape(im_shape), vmin=-.5, vmax=.5) plt.title(title) plt.imshow(im) plt.show() - print 'color: median nonzero %.2e' % (np.median(np.abs(nonzero)),) - print 'color: mean nonzero %.2e' % (np.mean(np.abs(nonzero)),) + print 'color: median nonzero %.2e' % (np.median(np.abs(nonzero)), ) + print 'color: mean nonzero %.2e' % (np.mean(np.abs(nonzero)), ) self.assertLess(np.mean(np.abs(nonzero)), 2e-2) self.assertLess(np.median(np.abs(nonzero)), 4.5e-3) @@ -488,10 +478,7 @@ def plt_imshow(im): if __name__ == '__main__': plt.ion() - visualize = True - #unittest.main() + TestRenderer.VISUALIZE = True suite = unittest.TestLoader().loadTestsFromTestCase(TestRenderer) unittest.TextTestRunner(verbosity=2).run(suite) plt.show() - # import pdb; pdb.set_trace() - diff --git a/opendr/test_sh.py b/opendr/test_sh.py index 5926ded..b702a01 100755 --- a/opendr/test_sh.py +++ b/opendr/test_sh.py @@ -10,17 +10,16 @@ import numpy as np from chumpy import Ch from chumpy.utils import row, col -from opendr.lighting import SphericalHarmonics try: import matplotlib.pyplot as plt except ImportError: from opendr.dummy import dummy as plt from opendr.topology import loop_subdivider +from opendr.lighting import SphericalHarmonics -visualize = False def getcam(): - from camera import ProjectPoints3D + from opendr.camera import ProjectPoints3D w = 640 h = 320 @@ -41,16 +40,16 @@ def getcam(): class TestSphericalHarmonics(unittest.TestCase): + VISUALIZE = False def test_spherical_harmonics(self): - global visualize - if visualize: + if self.VISUALIZE: plt.ion() # Get mesh v, f = get_sphere_mesh() - from geometry import VertNormals + from opendr.geometry import VertNormals vn = VertNormals(v=v, f=f) #vn = Ch(mesh.estimate_vertex_normals()) @@ -58,7 +57,7 @@ def test_spherical_harmonics(self): cam, frustum = getcam() # Get renderer - from renderer import ColoredRenderer + from opendr.renderer import ColoredRenderer cam.v = v cr = ColoredRenderer(f=f, camera=cam, frustum=frustum, v=v) @@ -78,13 +77,13 @@ def test_spherical_harmonics(self): newim = cr.r.reshape((frustum['height'], frustum['width'], 3)) ims_baseline.append(newim) - if visualize: + if self.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 + #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() @@ -92,50 +91,49 @@ def test_spherical_harmonics(self): 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') + for comp_idx in range(9): + if self.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 self.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 self.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 self.VISUALIZE: + plt.axis('off') def get_sphere_mesh(): - from util_tests import get_earthmesh + from opendr.util_tests import get_earthmesh mesh = get_earthmesh(np.zeros(3), np.zeros(3)) # load_mesh(filename) v, f = mesh.v*64., mesh.f - for i in range(3): + for _ in range(3): mtx, f = loop_subdivider(v, f) v = mtx.dot(v.ravel()).reshape((-1, 3)) v /= 200. @@ -144,13 +142,9 @@ def get_sphere_mesh(): return v, f - - if __name__ == '__main__': - visualize = True + TestSphericalHarmonics.VISUALIZE = True plt.ion() - #unittest.main() suite = unittest.TestLoader().loadTestsFromTestCase(TestSphericalHarmonics) unittest.TextTestRunner(verbosity=2).run(suite) plt.show() - # import pdb; pdb.set_trace() diff --git a/opendr/topology.py b/opendr/topology.py index f5c1993..058415a 100644 --- a/opendr/topology.py +++ b/opendr/topology.py @@ -14,9 +14,9 @@ def get_vert_connectivity(mesh_v, mesh_f): - """Returns a sparse matrix (of size #verts x #verts) where each nonzero + """Returns a sparse matrix(of size #verts x #verts) where each nonzero element indicates a neighborhood relation. For example, if there is a - nonzero element in position (15,12), that means vertex 15 is connected + nonzero element in position(15, 12), that means vertex 15 is connected by an edge to vertex 12.""" vpv = sp.csc_matrix((len(mesh_v), len(mesh_v))) @@ -76,7 +76,7 @@ def loop_subdivider(mesh_v, mesh_f): vc = get_vert_connectivity(mesh_v, mesh_f) ve = get_vertices_per_edge(mesh_v, mesh_f) - vo = get_vert_opposites_per_edge(mesh_v, mesh_f) + vo = get_vert_opposites_per_edge(mesh_f) # New values for each vertex for idx in xrange(len(mesh_v)): @@ -131,7 +131,7 @@ def loop_subdivider(mesh_v, mesh_f): f = [] - for f_i, old_f in enumerate(mesh_f): + for old_f in mesh_f: ff = np.concatenate((old_f, old_f)) for i in range(3): @@ -150,10 +150,10 @@ def loop_subdivider(mesh_v, mesh_f): IS = np.array(IS, dtype=np.uint32) JS = np.array(JS, dtype=np.uint32) - # for x,y,z coords + # for x, y, z coords IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) - data = np.concatenate ((data, data, data)) + data = np.concatenate((data, data, data)) ij = np.vstack((IS.flatten(), JS.flatten())) mtx = sp.csc_matrix((data, ij)) @@ -161,10 +161,10 @@ def loop_subdivider(mesh_v, mesh_f): return mtx, f -def get_vert_opposites_per_edge(mesh_v, mesh_f): +def get_vert_opposites_per_edge(mesh_f): """Returns a dictionary from vertidx-pairs to opposites. - For example, a key consist of [4,5)] meaning the edge between - vertices 4 and 5, and a value might be [10,11] which are the indices + For example, a key consist of [4, 5)] meaning the edge between + vertices 4 and 5, and a value might be [10, 11] which are the indices of the vertices opposing this edge.""" result = {} for f in mesh_f: diff --git a/opendr/utils.py b/opendr/utils.py index d7c9a8d..c54fa58 100644 --- a/opendr/utils.py +++ b/opendr/utils.py @@ -33,4 +33,4 @@ def wget(url, dest_fname=None): f.write(contents) source.close() except: - raise Exception('Unable to get url: %s' % (url,)) + raise Exception('Unable to get url: %s' % (url, )) From e01d7c46f8a8c1d09f6c4124f4c0dc90b9bc45ff Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Thu, 11 May 2017 13:08:17 -0400 Subject: [PATCH 53/56] fix more lint --- opendr/camera.py | 30 +++---- opendr/common.py | 142 +++++++++++++++------------------- opendr/everything.py | 14 ++-- opendr/filters.py | 61 ++++++--------- opendr/geometry.py | 47 +++++------ opendr/lighting.py | 27 +++---- opendr/rogrenderer.py | 48 +++++++----- opendr/serialization.py | 13 +--- opendr/simple.py | 50 ++++++------ opendr/slider_demo.py | 13 ++-- opendr/test_camera.py | 16 +--- opendr/test_depth_renderer.py | 40 +++------- 12 files changed, 220 insertions(+), 281 deletions(-) diff --git a/opendr/camera.py b/opendr/camera.py index e4b1805..1fc8671 100755 --- a/opendr/camera.py +++ b/opendr/camera.py @@ -27,6 +27,7 @@ def RigidTransformSlow(**kwargs): class RigidTransform(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'v', 'rt', 't' def compute_r(self): @@ -38,7 +39,7 @@ def compute_dr_wrt(self, wrt): return if wrt is self.t: - if not hasattr(self, '_drt') or self._drt.shape[0] != self.v.r.size: + if not hasattr(self, '_drt') or self._drt.shape[0] != self.v.r.size: # pylint: disable=access-member-before-definition IS = np.arange(self.v.r.size) JS = IS % 3 data = np.ones(len(IS)) @@ -56,12 +57,13 @@ def compute_dr_wrt(self, wrt): IS = np.repeat(np.arange(self.v.r.size), 3) JS = np.repeat(np.arange(self.v.r.size).reshape((-1, 3)), 3, axis=0) - data = np.vstack([rot for i in range(self.v.r.size/3)]) + data = np.vstack([rot for _ in range(self.v.r.size/3)]) result = sp.csc_matrix((data.ravel(), (IS.ravel(), JS.ravel()))) return result class ProjectPoints(Ch): + # pylint: disable=attribute-defined-outside-init dterms = 'v', 'rt', 't', 'f', 'c', 'k' def is_valid(self): @@ -98,7 +100,7 @@ def compute_r(self): elif len(k) == 5: k1, k2, p1, p2, k3 = k elif len(k) == 8: - k1, k2, p1, p2, k3, k4, k5, k6 = k + k1, k2, p1, p2, k3, k4, k5, k6 = k # pylint: disable=unused-variable else: raise AttributeError('k has wrong length, got %d, expect 4, 5 or 8' % len(k)) x2_y2 = x_y ** 2. @@ -115,7 +117,7 @@ def compute_dr_wrt(self, wrt): if wrt not in [self.v, self.rt, self.t, self.f, self.c, self.k]: return None - j = self.r_and_derivatives[1] + j = self.r_and_derivatives[1] # pylint: disable=unsubscriptable-object if wrt is self.rt: return j[:, :3] elif wrt is self.t: @@ -143,9 +145,9 @@ def unproject_points(self, uvd, camera_space=False): xyz_camera_space[:, :2] *= col(xyz_camera_space[:, 2]) # scale x, y by z if camera_space: return xyz_camera_space - other_answer = xyz_camera_space - row(cam.view_mtx[:, 3]) # translate - result = other_answer.dot(cam.view_mtx[:, :3]) # rotate - except: # slow way, probably not so good. But doesn't require cv2.undistortPoints. + other_answer = xyz_camera_space - row(cam.view_mtx[:, 3]) # translate pylint: disable=unsubscriptable-object + result = other_answer.dot(cam.view_mtx[:, :3]) # rotate pylint: disable=unsubscriptable-object + except: # slow way, probably not so good. But doesn't require cv2.undistortPoints. pylint: disable=bare-except cam.v = np.ones_like(uvd) ch.minimize(cam - uvd, x0=[cam.v], method='dogleg', options={'disp': 0}) result = cam.v.r @@ -186,6 +188,7 @@ def view_matrix(self): class ProjectPoints3D(ProjectPoints): + # pylint: disable=attribute-defined-outside-init dterms = 'v', 'rt', 't', 'f', 'c', 'k' def compute_r(self): @@ -194,7 +197,7 @@ def compute_r(self): @property def z_coords(self): - assert(self.v.r.shape[1] == 3) + assert self.v.r.shape[1] == 3 return RigidTransform(v=self.v, rt=self.rt, t=self.t)[:, 2] def compute_dr_wrt(self, wrt): @@ -221,14 +224,3 @@ def compute_dr_wrt(self, wrt): result = bigger.reshape((-1, bigger.shape[-1])) return result - - -def main(): - import unittest - from test_camera import TestCamera - suite = unittest.TestLoader().loadTestsFromTestCase(TestCamera) - unittest.TextTestRunner(verbosity=2).run(suite) - - -if __name__ == '__main__': - main() diff --git a/opendr/common.py b/opendr/common.py index 6833dba..6092f92 100755 --- a/opendr/common.py +++ b/opendr/common.py @@ -6,33 +6,22 @@ See LICENCE.txt for licensing and contact information. """ -import numpy as np from copy import deepcopy +import numpy as np import scipy.sparse as sp -from cvwrap import cv2 - -try: - from scipy.stats import nanmean as nanmean_impl -except: - from numpy import nanmean as nanmean_impl - from chumpy.utils import row, col -from contexts._constants import * # pylint: disable=unused-wildcard-import +from opendr.contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import +from opendr.cvwrap import cv2 -def nanmean(a, axis): - # don't call nan_to_num in here, unless you check that - # occlusion_test.py still works after you do it! - result = nanmean_impl(a, axis=axis) - return result def nangradients(arr): dy = np.expand_dims(arr[:-1, :, :] - arr[1:, :, :], axis=3) dx = np.expand_dims(arr[:, :-1, :] - arr[:, 1:, :], axis=3) dy = np.concatenate((dy[1:, :, :], dy[:-1, :, :]), axis=3) - dy = nanmean(dy, axis=3) + dy = np.nanmean(dy, axis=3) dx = np.concatenate((dx[:, 1:, :], dx[:, :-1, :]), axis=3) - dx = nanmean(dx, axis=3) + dx = np.nanmean(dx, axis=3) if arr.shape[2] > 1: gy, gx, _ = np.gradient(arr) @@ -68,10 +57,10 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid JS = np.concatenate([JS for i in range(n_channels)]) # Step 2: get the data ready, ie the actual values of the derivatives - ksize = 1 + # ksize = 1 bndf = bnd_bool.astype(np.float64) - nbndf = np.logical_not(bnd_bool).astype(np.float64) - sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5, 5] + # nbndf = np.logical_not(bnd_bool).astype(np.float64) + # sobel_normalizer = cv2.Sobel(np.asarray(np.tile(row(np.arange(10)), (10, 1)), np.float64), cv2.CV_64F, dx=1, dy=0, ksize=ksize)[5, 5] bnd_nan = bndf.reshape((observed.shape[0], observed.shape[1], -1)).copy() bnd_nan.ravel()[bnd_nan.ravel() > 0] = np.nan @@ -102,16 +91,15 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid # ydiffnb *= 0 # xdiffnb *= 0 - if False: - import matplotlib.pyplot as plt - plt.figure() - plt.subplot(121) - plt.imshow(xdiffnb) - plt.title('xdiffnb') - plt.subplot(122) - plt.imshow(xdiffbnd) - plt.title('xdiffbnd') - # import pdb; pdb.set_trace() + # import matplotlib.pyplot as plt + # plt.figure() + # plt.subplot(121) + # plt.imshow(xdiffnb) + # plt.title('xdiffnb') + # plt.subplot(122) + # plt.imshow(xdiffbnd) + # plt.title('xdiffbnd') + # # import pdb; pdb.set_trace() idxs = np.isnan(xdiffnb.ravel()) xdiffnb.ravel()[idxs] = xdiffbnd.ravel()[idxs] @@ -119,12 +107,12 @@ def dImage_wrt_2dVerts_bnd(observed, visible, visibility, barycentric, image_wid idxs = np.isnan(ydiffnb.ravel()) ydiffnb.ravel()[idxs] = ydiffbnd.ravel()[idxs] - if True: # should be right thing - xdiff = xdiffnb - ydiff = ydiffnb - else: #should be old way - xdiff = xdiffbnd - ydiff = ydiffbnd + # This should be right thing: + xdiff = xdiffnb + ydiff = ydiffnb + # The old way was: + # xdiff = xdiffbnd + # ydiff = ydiffbnd # TODO: NORMALIZER IS WRONG HERE @@ -233,14 +221,13 @@ def dImage_wrt_2dVerts(observed, visible, visibility, barycentric, image_width, def flow_to(self, v_next, cam_next): from chumpy.ch import MatVecMult - color_image = self.r + _ = self.r visibility = self.visibility_image pxpos = np.zeros_like(self.color_image) pxpos[:, :, 0] = np.tile(row(np.arange(self.color_image.shape[1])), (self.color_image.shape[0], 1)) pxpos[:, :, 2] = np.tile(col(np.arange(self.color_image.shape[0])), (1, self.color_image.shape[1])) visible = np.nonzero(visibility.ravel() != 4294967295)[0] - num_visible = len(visible) barycentric = self.barycentric_image @@ -291,7 +278,7 @@ def dr_wrt_bgcolor(visibility, frustum, num_channels): # color image, so 3 channels IS = np.concatenate([IS*num_channels+k for k in range(num_channels)]) JS = np.concatenate([JS*num_channels+k for k in range(num_channels)]) - data = np.concatenate([data for i in range(num_channels)]) + data = np.concatenate([data for _ in range(num_channels)]) # IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) # JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) # data = np.concatenate((data, data, data)) @@ -311,7 +298,7 @@ def dr_wrt_vc(visible, visibility, f, barycentric, frustum, vc_size, num_channel IS = np.concatenate([IS*num_channels+k for k in range(num_channels)]) JS = np.concatenate([JS*num_channels+k for k in range(num_channels)]) - data = np.concatenate([data for i in range(num_channels)]) + data = np.concatenate([data for _ in range(num_channels)]) # IS = np.concatenate((IS*3, IS*3+1, IS*3+2)) # JS = np.concatenate((JS*3, JS*3+1, JS*3+2)) # data = np.concatenate((data, data, data)) @@ -359,15 +346,14 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None, x0=None, x1=None, y idxs = result2 != 4294967295 result2[idxs] = faces_to_draw[result2[idxs]] - if False: - result2[result2 == 4294967295] = 0 - import matplotlib.pyplot as plt - result2 = result2.reshape(result.shape[:2]) - plt.figure() - plt.subplot(121) - plt.imshow(result.squeeze()) - plt.subplot(122) - plt.imshow(result2.squeeze()) + # result2[result2 == 4294967295] = 0 + # import matplotlib.pyplot as plt + # result2 = result2.reshape(result.shape[:2]) + # plt.figure() + # plt.subplot(121) + # plt.imshow(result.squeeze()) + # plt.subplot(122) + # plt.imshow(result2.squeeze()) result2 = result2.reshape(result.shape[:2]) result = result2 * bbi + result * (1 - bbi) @@ -505,33 +491,33 @@ def draw_barycentric_image_internal(gl, v, f): # May end up using this, maybe not -def get_inbetween_boundaries(self): - camera = self.camera - frustum = self.frustum - w = frustum['width'] - h = frustum['height'] - far = frustum['far'] - near = frustum['near'] - - self.glb.Viewport(0, 0, w-1, h) - _setup_camera(self.glb, - camera.c.r[0]-.5, camera.c.r[1], - camera.f.r[0], camera.f.r[1], - w-1, h, - near, far, - camera.view_matrix, camera.k) - bnd_x = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:, :-1] - - self.glb.Viewport(0, 0, w, h-1) - _setup_camera(self.glb, - camera.c.r[0], camera.c.r[1]-.5, - camera.f.r[0], camera.f.r[1], - w, h-1, - near, far, - camera.view_matrix, camera.k) - bnd_y = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:-1, :] - - # Put things back to normal - self.glb.Viewport(0, 0, w, h) - setup_camera(self.glb, camera, frustum) - return bnd_x, bnd_y +# def get_inbetween_boundaries(self): +# camera = self.camera +# frustum = self.frustum +# w = frustum['width'] +# h = frustum['height'] +# far = frustum['far'] +# near = frustum['near'] + +# self.glb.Viewport(0, 0, w-1, h) +# _setup_camera(self.glb, +# camera.c.r[0]-.5, camera.c.r[1], +# camera.f.r[0], camera.f.r[1], +# w-1, h, +# near, far, +# camera.view_matrix, camera.k) +# bnd_x = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:, :-1] + +# self.glb.Viewport(0, 0, w, h-1) +# _setup_camera(self.glb, +# camera.c.r[0], camera.c.r[1]-.5, +# camera.f.r[0], camera.f.r[1], +# w, h-1, +# near, far, +# camera.view_matrix, camera.k) +# bnd_y = draw_boundaryid_image(self.glb, self.v.r, self.f, self.vpe, self.fpe, self.camera)[:-1, :] + +# # Put things back to normal +# self.glb.Viewport(0, 0, w, h) +# setup_camera(self.glb, camera, frustum) +# return bnd_x, bnd_y diff --git a/opendr/everything.py b/opendr/everything.py index 8b07c66..725394e 100644 --- a/opendr/everything.py +++ b/opendr/everything.py @@ -2,28 +2,28 @@ import opendr.camera from opendr.camera import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += camera.__all__ +__all__ += opendr.camera.__all__ import opendr.renderer from opendr.renderer import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += renderer.__all__ +__all__ += opendr.renderer.__all__ import opendr.lighting from opendr.lighting import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += lighting.__all__ +__all__ += opendr.lighting.__all__ import opendr.topology from opendr.topology import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += topology.__all__ +__all__ += opendr.topology.__all__ import opendr.geometry from opendr.geometry import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += geometry.__all__ +__all__ += opendr.geometry.__all__ import opendr.serialization from opendr.serialization import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += serialization.__all__ +__all__ += opendr.serialization.__all__ import opendr.filters from opendr.filters import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += filters.__all__ +__all__ += opendr.filters.__all__ diff --git a/opendr/filters.py b/opendr/filters.py index 615b585..1f7c911 100755 --- a/opendr/filters.py +++ b/opendr/filters.py @@ -8,42 +8,40 @@ __all__ = ['gaussian_pyramid', 'laplacian_pyramid', 'GaussPyrDownOne'] -from cvwrap import cv2 -import chumpy as ch -import numpy as np from copy import deepcopy +import numpy as np import scipy.sparse as sp -from chumpy.ch import MatVecMult, Ch, depends_on +import chumpy as ch +from chumpy.ch import MatVecMult, Ch +from opendr.cvwrap import cv2 def laplacian_pyramid(input_objective, imshape, normalization, n_levels, as_list): if normalization is None: - norm2 = lambda x : x + norm2 = lambda x: x elif normalization is 'SSE': - norm2 = lambda x : x / np.sqrt(np.sum(x.r**2.)) + norm2 = lambda x: x / np.sqrt(np.sum(x.r**2.)) elif normalization is 'size': - norm2 = lambda x : x / x.r.size + norm2 = lambda x: x / x.r.size else: norm2 = normalization imshape = [int(x) for x in imshape] output_objs = [] - for level in range(n_levels): + for _ in range(n_levels): - blur_mtx = filter_for(imshape[0], imshape[1], imshape[2] if len(imshape)>2 else 1, kernel = GaussianKernel2D(3, 1)) + blur_mtx = filter_for(imshape[0], imshape[1], imshape[2] if len(imshape) > 2 else 1, kernel=GaussianKernel2D(3, 1)) blurred = MatVecMult(blur_mtx, input_objective).reshape(imshape) output_objs.append(norm2(input_objective - blurred)) - halfsampler_mtx, imshape = halfsampler_for(imshape) input_objective = MatVecMult(halfsampler_mtx, blurred.ravel()).reshape(imshape) output_objs.append(norm2(input_objective).reshape(imshape)) - return output_objs if as_list else reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), output_objs) - + return output_objs if as_list else reduce(lambda x, y: ch.concatenate((x.ravel(), y.ravel())), output_objs) def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_levels=3, as_list=False, label=None): @@ -52,11 +50,11 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level imshape = input_objective.shape if normalization is None: - norm2 = lambda x : x + norm2 = lambda x: x elif normalization is 'SSE': - norm2 = lambda x : x / np.sqrt(np.sum(x.r**2.)) + norm2 = lambda x: x / np.sqrt(np.sum(x.r**2.)) elif normalization is 'size': - norm2 = lambda x : x / x.r.size + norm2 = lambda x: x / x.r.size else: norm2 = normalization @@ -67,16 +65,17 @@ def gaussian_pyramid(input_objective, imshape=None, normalization='SSE', n_level output_objectives = [input_objective] for ik in range(n_levels): - cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape) + cur_obj = GaussPyrDownOne(px=cur_obj, im_shape=cur_imshape) cur_imshape = cur_obj.output_shape output_objectives.append(norm2(cur_obj) if label is None else norm2(cur_obj) >> '%s%d' % (label, ik)) if not as_list: - andit = lambda a : reduce(lambda x, y : ch.concatenate((x.ravel(), y.ravel())), a) + andit = lambda a: reduce(lambda x, y: ch.concatenate((x.ravel(), y.ravel())), a) output_objectives = andit(output_objectives) return output_objectives + def GaussianKernel2D(ksize, sigma): if ksize % 2 != 1: raise Exception('ksize should be an odd number') @@ -87,20 +86,21 @@ def GaussianKernel2D(ksize, sigma): class GaussPyrDownOneOld(Ch): - terms = 'im_shape', 'want_downsampling', 'kernel' + # pylint: disable=attribute-defined-outside-init + terms = 'im_shape', 'want_downsampling', 'kernel' dterms = 'px' # Approximation to a 3x3 Gaussian kernel default_kernel = GaussianKernel2D(3, 1) - def on_changed(self, which): + def on_changed(self, which): # pylint: disable=arguments-differ if not hasattr(self, 'kernel'): self.kernel = self.default_kernel.copy() if 'im_shape' in which: sh = self.im_shape self.transf_mtx, self._output_shape = filter_for_nopadding(sh, self.kernel) - if True: # self.want_downsampling: <-- setting want_downsampling to "False" is broken + if True: # self.want_downsampling: <-- setting want_downsampling to "False" is broken pylint: disable=using-constant-test halfsampler, self._output_shape = halfsampler_for(self._output_shape) self.transf_mtx = halfsampler.dot(self.transf_mtx) self.add_dterm('transform', MatVecMult(mtx=self.transf_mtx)) @@ -108,7 +108,6 @@ def on_changed(self, which): if 'px' in which: self.transform.vec = self.px - @property def output_shape(self): self._call_on_changed() # trigger changes from im_shape @@ -124,9 +123,9 @@ def compute_dr_wrt(self, wrt): return 1 - class GaussPyrDownOneNew(Ch): - terms = 'im_shape' + # pylint: disable=attribute-defined-outside-init + terms = 'im_shape' dterms = 'px' @property @@ -139,12 +138,13 @@ def compute_r(self): def compute_dr_wrt(self, wrt): if wrt is self.px: - linop = lambda x : cv2.pyrDown(x.reshape(self.im_shape)).ravel() + linop = lambda x: cv2.pyrDown(x.reshape(self.im_shape)).ravel() return sp.linalg.LinearOperator((self.r.size, self.px.size), linop) GaussPyrDownOne = GaussPyrDownOneOld + def halfsampler_for(shape): h = int(shape[0]) w = int(shape[1]) @@ -190,7 +190,6 @@ def filter_for_nopadding(shape, kernel): IS.append(np.arange(new_shape[0]*new_shape[1])) data.append(np.ones(IS[-1].size) * kernel[ky, kx]) - IS = np.concatenate(IS) JS = np.concatenate(JS) data = np.concatenate(data) @@ -250,15 +249,3 @@ def filter_for(h, w, d, kernel): # return sp.csc_matrix((data, (IS, JS)), shape=(h*w*d, h*w*d)) - - - - -def main(): - pass - - - - -if __name__ == '__main__': - main() diff --git a/opendr/geometry.py b/opendr/geometry.py index 783bffb..844e9a7 100755 --- a/opendr/geometry.py +++ b/opendr/geometry.py @@ -58,22 +58,21 @@ def compute_dr_wrt(self, wrt): return None v = self.v.r.reshape(-1, 3) - blocks = -np.einsum('ij, ik->ijk', v, v) * (self.ss**(-3./2.)).reshape((-1, 1, 1)) + blocks = np.negative(np.einsum('ij, ik->ijk', v, v) * (self.ss**(-3./2.)).reshape((-1, 1, 1))) for i in range(3): blocks[:, i, i] += self.s_inv - if True: - data = blocks.ravel() - indptr = np.arange(0, (self.v.r.size+1)*3, 3) - indices = col(np.arange(0, self.v.r.size)) - indices = np.hstack([indices, indices, indices]) - indices = indices.reshape((-1, 3, 3)) - indices = indices.transpose((0, 2, 1)).ravel() - result = sp.csc_matrix((data, indices, indptr), shape=(self.v.r.size, self.v.r.size)) - return result - else: - matvec = lambda x: np.einsum('ijk, ik->ij', blocks, x.reshape((blocks.shape[0], 3))).ravel() - return sp.linalg.LinearOperator((self.v.r.size, self.v.r.size), matvec=matvec) + data = blocks.ravel() + indptr = np.arange(0, (self.v.r.size+1)*3, 3) + indices = col(np.arange(0, self.v.r.size)) + indices = np.hstack([indices, indices, indices]) + indices = indices.reshape((-1, 3, 3)) + indices = indices.transpose((0, 2, 1)).ravel() + result = sp.csc_matrix((data, indices, indptr), shape=(self.v.r.size, self.v.r.size)) + return result + # Alternative?: + # matvec = lambda x: np.einsum('ijk, ik->ij', blocks, x.reshape((blocks.shape[0], 3))).ravel() + # return sp.linalg.LinearOperator((self.v.r.size, self.v.r.size), matvec=matvec) class Sum3xN(Ch): @@ -147,7 +146,8 @@ def face_bases(v, f): # Problem: cross-product is proportional in length to len(t1)*len(t2) # Solution: divide by sqrt(sqrt(len(cross-product))) - t3 = CrossProduct(t1, t2).reshape((-1, 3)); t3 = t3 / col(ch.sum(t3**2., axis=1)**.25) + t3 = CrossProduct(t1, t2).reshape((-1, 3)) + t3 = t3 / col(ch.sum(t3**2., axis=1)**.25) result = ch.hstack((t1, t2, t3)).reshape((-1, 3, 3)) return result @@ -219,7 +219,7 @@ def compute_dr_wrt(self, wrt): def TriArea(v_init, f, normalize): """ Returns a Ch object whose only attribute "v" represents the flattened vertices.""" - + # pylint: disable=unnecessary-lambda if normalize: nm = lambda x: NormalizedNx3(x) else: @@ -229,24 +229,27 @@ def TriArea(v_init, f, normalize): return result -def AcosTriAngles(v, f, normalize): +def AcosTriAngles(v_init, f, normalize): """ Returns a Ch object whose only attribute "v" represents the flattened vertices.""" + # pylint: disable=unnecessary-lambda if normalize: nm = lambda x: NormalizedNx3(x) else: nm = lambda x: x - return Ch(lambda v: - Sum3xN(NormalizedNx3(TriEdges(f, 1, 0, nm(v))) * NormalizedNx3(TriEdges(f, 2, 0, nm(v)))) & - Sum3xN(NormalizedNx3(TriEdges(f, 2, 1, nm(v))) * NormalizedNx3(TriEdges(f, 0, 1, nm(v)))) & - Sum3xN(NormalizedNx3(TriEdges(f, 0, 2, nm(v))) * NormalizedNx3(TriEdges(f, 1, 2, nm(v))))) + result = Ch(lambda v: + Sum3xN(NormalizedNx3(TriEdges(f, 1, 0, nm(v))) * NormalizedNx3(TriEdges(f, 2, 0, nm(v)))) & + Sum3xN(NormalizedNx3(TriEdges(f, 2, 1, nm(v))) * NormalizedNx3(TriEdges(f, 0, 1, nm(v)))) & + Sum3xN(NormalizedNx3(TriEdges(f, 0, 2, nm(v))) * NormalizedNx3(TriEdges(f, 1, 2, nm(v))))) + result.v = v_init + return result class VertNormals(Ch): """If normalized == True, normals are normalized; otherwise they'll be about as long as neighboring edges.""" - # pylint: disable=attribute-defined-outside-init + # pylint: disable=attribute-defined-outside-init, access-member-before-definition dterms = 'v' terms = 'f', 'normalized' @@ -338,7 +341,7 @@ def _edges_for(v, f, cplus, cminus): v.reshape(-1, 3)[f[:, cminus], :]).ravel() class CrossProduct(Ch): - # pylint: disable=attribute-defined-outside-init + # pylint: disable=attribute-defined-outside-init, access-member-before-definition terms = [] dterms = 'a', 'b' diff --git a/opendr/lighting.py b/opendr/lighting.py index 7711a7b..bdb40fc 100755 --- a/opendr/lighting.py +++ b/opendr/lighting.py @@ -9,11 +9,8 @@ __all__ = ['LambertianPointLight', 'SphericalHarmonics'] -import os -import sys import logging import numpy as np -import scipy import scipy.sparse as sp import chumpy as ch from chumpy.utils import row, col @@ -75,7 +72,7 @@ def on_changed(self, which): # pylint: disable=arguments-differ self.sh_coeffs = real_sh_coeff(vn) self.num_verts = self.sh_coeffs.shape[0] - if 'light_color' in which or self.mtx.shape[1] != self.num_verts: + if 'light_color' in which or self.mtx.shape[1] != self.num_verts: # pylint: disable=access-member-before-definition nc = self.num_channels IS = np.arange(self.num_verts*nc) JS = np.repeat(np.arange(self.num_verts), nc) @@ -143,31 +140,31 @@ def compute_dr_wrt(self, wrt): return gr_equal_zero.dot(result) -def lambertian_spotlight(v, vn, pos, dir, spot_exponent, camcoord=False, camera_t=None, camera_rt=None): +def lambertian_spotlight(v, vn, light_pos, light_dir, spot_exponent, camcoord=False, camera_t=None, camera_rt=None): """ :param v: vertices :param vn: vertex normals :param light_pos: light position :param light_dir: light direction :param spot_exponent: spot exponent(a la opengl) - :param camcoord: if True, then pos and dir are wrt the camera + :param camcoord: if True, then light_pos and light_dir are wrt the camera :param camera_t: 3-vector indicating translation of camera :param camera_rt: 3-vector indicating direction of camera :return: Vx1 array of brightness """ - if camcoord: # Transform pos and dir from camera to world coordinate system + if camcoord: # Transform light_pos and light_dir from camera to world coordinate system assert camera_t is not None and camera_rt is not None from opendr.geometry import Rodrigues rot = Rodrigues(rt=camera_rt) - pos = rot.T.dot(pos-camera_t) - dir = rot.T.dot(dir) + light_pos = rot.T.dot(light_pos-camera_t) + light_dir = rot.T.dot(light_dir) - dir = dir / ch.sqrt(ch.sum(dir**2.)) - v_minus_light = v - pos.reshape((1, 3)) + light_dir = light_dir / ch.sqrt(ch.sum(light_dir**2.)) + v_minus_light = v - light_pos.reshape((1, 3)) v_distances = ch.sqrt(ch.sum(v_minus_light**2, axis=1)) v_minus_light_normed = v_minus_light / v_distances.reshape((-1, 1)) - cosangle = v_minus_light_normed.dot(dir.reshape((3, 1))) + cosangle = v_minus_light_normed.dot(light_dir.reshape((3, 1))) light_dot_normal = ch.sum(vn*v_minus_light_normed, axis=1) light_dot_normal.label = 'light_dot_normal' cosangle.label = 'cosangle' @@ -195,7 +192,7 @@ def on_changed(self, which): # pylint: disable=arguments-differ else: self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) if not hasattr(self, 'ldn'): - self.ldn = LightDotNormal(self.v.r.size/3) + self.ldn = LightDotNormal() if not hasattr(self, 'vn'): logger.info('LambertianPointLight using auto-normals. This will be slow for derivative-free computations.') self.vn = VertNormals(f=self.f, v=self.v) @@ -238,10 +235,10 @@ def compute_dr_wrt(self, wrt): # ij = np.vstack((row(IS), row(JS))) # return sp.csc_matrix((data, ij), shape=(num_verts*3, 3)) -def LightDotNormal(num_verts): +def LightDotNormal(): normalize_rows = lambda v: v / col(ch.sqrt(ch.sum(v.reshape((-1, 3))**2, axis=1))) sum_rows = lambda v: ch.sum(v.reshape((-1, 3)), axis=1) - return Ch(lambda light_pos, v, vn : + return Ch(lambda light_pos, v, vn: sum_rows(normalize_rows(light_pos.reshape((1, 3)) - v.reshape((-1, 3))) * vn.reshape((-1, 3)))) diff --git a/opendr/rogrenderer.py b/opendr/rogrenderer.py index 0242d9e..2c175b3 100644 --- a/opendr/rogrenderer.py +++ b/opendr/rogrenderer.py @@ -4,59 +4,63 @@ See LICENCE.txt for licensing and contact information. """ -import sys -import os -from cvwrap import cv2 import numpy as np - +from opendr.cvwrap import cv2 from opendr.renderer import TexturedRenderer -from opendr.lighting import LambertianPointLight -#from test_renderer import get_camera, convertCam, get_earthmesh class RogTexRenderer(TexturedRenderer): + # pylint: disable=attribute-defined-outside-init terms = list(TexturedRenderer.terms) + ['sigma_big', 'sigma_small', 'bckground_mask'] - def draw_color_image(self, with_vertex_colors): - result = super(self.__class__, self).draw_color_image(with_vertex_colors) + def draw_color_image(self, with_vertex_colors): # pylint: disable=arguments-differ + result = super(RogTexRenderer, self).draw_color_image(with_vertex_colors) return self.compute_rog(result) def compute_rog(self, im, is_real=False): - if(self.sigma_small >= self.sigma_big) or(self.sigma_small == 0): return im + if (self.sigma_small >= self.sigma_big) or (self.sigma_small == 0): + return im if self.frustum['height'] != np.shape(im)[0]: im = cv2.resize(im, (self.frustum['width'], self.frustum['height'])) - if(len(im.shape) == 3): im = np.mean(im, axis=2) + if len(im.shape) == 3: + im = np.mean(im, axis=2) im = np.asarray(im, np.float64)/255. visibility = super(self.__class__, self).visibility_image im[visibility == 4294967295] = np.nan ksize = self.sigma_small*4 - if ksize % 2 == 0: ksize += 1 + if ksize % 2 == 0: + ksize += 1 smblur = cv2.GaussianBlur(im, (ksize, ksize), self.sigma_small) ksize = self.sigma_big*4 - if ksize % 2 == 0: ksize += 1 + if ksize % 2 == 0: + ksize += 1 bgblur = cv2.GaussianBlur(im, (ksize, ksize), self.sigma_big) # FIXME? zero values im = smblur / bgblur if is_real: - self.bckground_mask = np.ones_like(im); self.bckground_mask[np.isnan(im)] = np.nan + self.bckground_mask = np.ones_like(im) + self.bckground_mask[np.isnan(im)] = np.nan im.ravel()[np.isnan(im.ravel())] = 0 - if hasattr(self, 'bckground_mask'): im.ravel()[np.isnan(self.bckground_mask.ravel())] = 0 + if hasattr(self, 'bckground_mask'): + im.ravel()[np.isnan(self.bckground_mask.ravel())] = 0 return im +def load_basics(): + from opendr.test_renderer import getcam + from opendr.util_tests import get_earthmesh + from opendr.lighting import LambertianPointLight -"""def load_basics(): np.random.seed(0) - camera = get_camera(scaling=.4) - camera, frustum = convertCam(camera) - mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation = np.array([0, 0, 0])) + camera, frustum = getcam() + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([0, 0, 0])) lighting = LambertianPointLight( f=mesh.f, @@ -71,13 +75,12 @@ def compute_rog(self, im, is_real=False): RogTexRenderer(f=mesh.f, vc=mesh.vc, v=mesh.v, camera=camera, frustum=frustum, texture_image=mesh.texture_image, vt=mesh.vt, ft=mesh.ft, bgcolor=bgcolor, sigma_small=3, sigma_big=5)] return mesh, lighting, camera, frustum, renderers -""" -if __name__ == '__main__': +def main(): import matplotlib.pyplot as plt - mesh, lighting, camera, frustum, renderers = load_basics() + _, _, _, _, renderers = load_basics() plt.ion() # Show default textured renderer @@ -91,3 +94,6 @@ def compute_rog(self, im, is_real=False): r2 /= np.max(r2.ravel()) plt.imshow(r2) # import pdb; pdb.set_trace() + +if __name__ == '__main__': + main() diff --git a/opendr/serialization.py b/opendr/serialization.py index cd05db9..01e5d81 100644 --- a/opendr/serialization.py +++ b/opendr/serialization.py @@ -9,9 +9,9 @@ __all__ = ['load_mesh', 'load_image'] from os.path import split, splitext, join, exists, normpath -from cvwrap import cv2 import numpy as np -from dummy import Minimal +from opendr.cvwrap import cv2 +from opendr.dummy import Minimal def load_image(filename): @@ -122,7 +122,6 @@ def read_obj(filename): def read_ply(filename): - import numpy as np str2dtype = { 'char': np.int8, 'uchar': np.uint8, @@ -159,7 +158,7 @@ def read_ply(filename): if len(tokens) <= 0: continue if tokens[0] == 'format': - format = tokens[1] + ply_format = tokens[1] elif tokens[0] == 'element': elements.append({'name': tokens[1], 'len': int(tokens[2]), 'properties': []}) @@ -171,7 +170,7 @@ def read_ply(filename): elements[-1]['properties'].append(prop) newelems = {} - if format == 'ascii': + if ply_format == 'ascii': body = body.split(newline) while len(elements) > 0: element = elements.pop(0) @@ -195,7 +194,3 @@ def read_ply(filename): mesh = Minimal(v=v, f=f) return mesh - -if __name__ == '__main__': - pass - diff --git a/opendr/simple.py b/opendr/simple.py index 12ef192..40df5e5 100644 --- a/opendr/simple.py +++ b/opendr/simple.py @@ -1,36 +1,36 @@ __all__ = [] -import camera -from camera import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += camera.__all__ +import opendr.camera +from opendr.camera import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.camera.__all__ -import renderer -from renderer import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += renderer.__all__ +import opendr.renderer +from opendr.renderer import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.renderer.__all__ -import lighting -from lighting import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += lighting.__all__ +import opendr.lighting +from opendr.lighting import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.lighting.__all__ -import topology -from topology import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += topology.__all__ +import opendr.topology +from opendr.topology import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.topology.__all__ -import geometry -from geometry import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += geometry.__all__ +import opendr.geometry +from opendr.geometry import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.geometry.__all__ -import serialization -from serialization import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += serialization.__all__ +import opendr.serialization +from opendr.serialization import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.serialization.__all__ -import utils -from utils import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += utils.__all__ +import opendr.utils +from opendr.utils import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.utils.__all__ -import filters -from filters import * # pylint: disable=wildcard-import, unused-wildcard-import -__all__ += filters.__all__ +import opendr.filters +from opendr.filters import * # pylint: disable=wildcard-import, unused-wildcard-import +__all__ += opendr.filters.__all__ -import chumpy as ch +import chumpy as ch # pylint: disable=unused-import __all__ += ['ch'] diff --git a/opendr/slider_demo.py b/opendr/slider_demo.py index a41630c..750e0bd 100644 --- a/opendr/slider_demo.py +++ b/opendr/slider_demo.py @@ -1,15 +1,14 @@ -from cvwrap import cv2 +from copy import deepcopy import numpy as np import chumpy as ch -from copy import deepcopy +from opendr.cvwrap import cv2 -def nothing(x): +def nothing(_): pass def get_renderer(): - import chumpy as ch - from opendr.everything import * # pylint: disable=unused-wildcard-import, unused-variable + from opendr.everything import load_mesh, TexturedRenderer, ProjectPoints, SphericalHarmonics, VertNormals # Load mesh m = load_mesh('/Users/matt/geist/OpenDR/test_dr/nasa_earth.obj') @@ -29,7 +28,6 @@ def get_renderer(): def main(): # Create a black image, a window - img = np.zeros((300, 512, 3), np.uint8) cv2.namedWindow('image') cv2.namedWindow('derivatives') @@ -52,7 +50,7 @@ def main(): old_tracked = tracked cv2.setTrackbarPos('sph0', 'image', 800) - while(1): + while True: cv2.imshow('image', rn.r) k = cv2.waitKey(1) & 0xFF if k == 27: @@ -62,7 +60,6 @@ def main(): v[:] = np.array(cv2.getTrackbarPos(k, 'image')).astype(np.float32)*4/cnst if tracked[k].r[0] != old_tracked[k].r[0]: drim = rn.dr_wrt(v).reshape(rn.shape) - mn = np.mean(drim) drim /= np.max(np.abs(drim.ravel()))*2. drim += .5 # drim = drim - np.min(drim) diff --git a/opendr/test_camera.py b/opendr/test_camera.py index 8c5efc4..531bd42 100755 --- a/opendr/test_camera.py +++ b/opendr/test_camera.py @@ -8,11 +8,8 @@ import unittest import numpy as np - -from camera import * import chumpy as ch - - +from opendr.camera import ProjectPoints, ProjectPoints3D class TestCamera(unittest.TestCase): @@ -32,14 +29,14 @@ def get_cam_params(self): return cam_params def test_project_points_without_derivatives(self): - from util_tests import get_earthmesh + from opendr.util_tests import get_earthmesh cam_params = self.get_cam_params() - mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation = np.array([0, 0, 0])) + mesh = get_earthmesh(trans=np.array([0, 0, 5]), rotation=np.array([0, 0, 0])) pp = ProjectPoints(f=cam_params['f'], rt=cam_params['rt'], t=cam_params['t'], k=cam_params['k'], c=cam_params['c']) pp.v = mesh.v - np.testing.assert_array_almost_equal(pp.r, pp.r_and_derivatives[0].squeeze()) + np.testing.assert_array_almost_equal(pp.r, pp.r_and_derivatives[0].squeeze()) # FIXME pylint: disable=unsubscriptable-object def test_project_points(self): self.project_points(ProjectPoints) @@ -91,8 +88,3 @@ def project_points(self, cls): self.assertTrue(aa is not bb) else: self.assertTrue(aa is bb) - - -if __name__ == '__main__': - unittest.main() - diff --git a/opendr/test_depth_renderer.py b/opendr/test_depth_renderer.py index 4e0fe00..5266e3c 100644 --- a/opendr/test_depth_renderer.py +++ b/opendr/test_depth_renderer.py @@ -1,28 +1,27 @@ -from renderer import DepthRenderer -import numpy as np import unittest +import numpy as np +import chumpy as ch +from chumpy.utils import row +from opendr.renderer import DepthRenderer +from opendr.util_tests import get_earthmesh +from opendr.camera import ProjectPoints -visualize = False - class TestDepthRenderer(unittest.TestCase): + VISUALIZE = False def setUp(self): np.random.seed(0) def test_depth_image(self): # Create renderer - import chumpy as ch - from renderer import DepthRenderer rn = DepthRenderer() # Assign attributes to renderer - from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0, 0, 0]), rotation=ch.zeros(3)) m.v = m.v * .01 m.v[:, 2] += 4 w, h = (320, 240) - from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, vc=m.vc*0+1, bgcolor=ch.zeros(3)) @@ -39,23 +38,16 @@ def test_depth_image(self): self.assertLess(np.abs(rn.r[h/2, w/2] - 3.98), 1e-5) def test_derivatives(self): - import chumpy as ch - from chumpy.utils import row - import numpy as np - from renderer import DepthRenderer - rn = DepthRenderer() # Assign attributes to renderer - from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) - from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) - if visualize: + if self.VISUALIZE: import matplotlib.pyplot as plt plt.figure() for which in range(3): @@ -74,7 +66,7 @@ def test_derivatives(self): self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .031) - if visualize: + if self.VISUALIZE: plt.subplot(2, 3, which+1) plt.imshow(dr_pred) plt.clim(-.01, .01) @@ -85,22 +77,16 @@ def test_derivatives(self): plt.title('pred') def test_derivatives2(self): - import chumpy as ch - import numpy as np - from renderer import DepthRenderer - rn = DepthRenderer() # Assign attributes to renderer - from util_tests import get_earthmesh m = get_earthmesh(trans=ch.array([0, 0, 4]), rotation=ch.zeros(3)) w, h = (320, 240) - from camera import ProjectPoints rn.camera = ProjectPoints(v=m.v, rt=ch.zeros(3), t=ch.zeros(3), f=ch.array([w, w])/2., c=ch.array([w, h])/2., k=ch.zeros(5)) rn.frustum = {'near': 1., 'far': 10., 'width': w, 'height': h} rn.set(v=m.v, f=m.f, bgcolor=ch.zeros(3)) - if visualize: + if self.VISUALIZE: import matplotlib.pyplot as plt plt.ion() plt.figure() @@ -120,7 +106,7 @@ def test_derivatives2(self): self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .024) - if visualize: + if self.VISUALIZE: plt.subplot(2, 3, which+1) plt.imshow(dr_pred) plt.clim(-.01, .01) @@ -133,8 +119,6 @@ def test_derivatives2(self): plt.show() if __name__ == '__main__': - visualize = True - #unittest.main() + TestDepthRenderer.VISUALIZE = True suite = unittest.TestLoader().loadTestsFromTestCase(TestDepthRenderer) unittest.TextTestRunner(verbosity=2).run(suite) - # import pdb; pdb.set_trace() From 0173844d556563bc509f419246167c0ca1d06380 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Thu, 11 May 2017 13:15:19 -0400 Subject: [PATCH 54/56] pylint disable in autogened _constants --- opendr/contexts/autogen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendr/contexts/autogen.py b/opendr/contexts/autogen.py index 8d1e665..f55fd8d 100755 --- a/opendr/contexts/autogen.py +++ b/opendr/contexts/autogen.py @@ -144,7 +144,7 @@ def main(): fp.write(functions) fp.write(extfunctions) - constants_all = "__all__ = [%s]" % (constants_all,) + constants_all = "# pylint: disable=bad-whitespace, too-many-lines\n" + "__all__ = [%s]" % (constants_all,) constants = constants_all + '\n' + constants From 9687106433303ff9b392b503a3a9a2cdce86a6fe Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Thu, 11 May 2017 13:25:36 -0400 Subject: [PATCH 55/56] install chumpy from pypi in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ab0bf64..50aad99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ before_install: - sudo apt-get install -qq python-dev gfortran python-opencv pkg-config liblapack-dev - pip install --upgrade pip - pip install Cython - - travis_wait pip install git+git://github.com/mattloper/chumpy.git + - pip install chumpy install: - pip install -r requirements.txt script: make test From 3ee98dbbca82420d694bcd31e09bbd1024050800 Mon Sep 17 00:00:00 2001 From: Alex Weiss Date: Thu, 11 May 2017 13:29:15 -0400 Subject: [PATCH 56/56] preinstall numpy and scipy in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 50aad99..3345023 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_install: - sudo apt-get update -qq - sudo apt-get install -qq python-dev gfortran python-opencv pkg-config liblapack-dev - pip install --upgrade pip - - pip install Cython + - pip install numpy scipy Cython - pip install chumpy install: - pip install -r requirements.txt