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/.travis.yml b/.travis.yml
index ab0bf64..3345023 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,8 +8,8 @@ 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
- - travis_wait pip install git+git://github.com/mattloper/chumpy.git
+ - pip install numpy scipy Cython
+ - pip install chumpy
install:
- pip install -r requirements.txt
script: make test
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
new file mode 100644
index 0000000..9c96e5f
--- /dev/null
+++ b/circle.yml
@@ -0,0 +1,22 @@
+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 numpy scipy cython
+ - pip install -r requirements_dev.txt
+ - pip install -e .
+
+test:
+ override:
+ - rake test
+ - rake lint
diff --git a/contexts/draw_triangle_shaders_2_1.py b/contexts/draw_triangle_shaders_2_1.py
deleted file mode 100644
index d57957c..0000000
--- a/contexts/draw_triangle_shaders_2_1.py
+++ /dev/null
@@ -1,84 +0,0 @@
-__author__ = 'matt'
-
-import cv2
-import numpy as np
-from opendr.contexts._constants import *
-
-import platform
-if platform.system()=='Darwin':
- from ctx_mac import OsContext
-else:
- from ctx_mesa import OsContext
-
-fs_source = """
-#version 120
-
-void main(void) {
- gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-}
-"""
-
-vs_source = """
-#version 120
-void main(void) {
- //gl_Position = ftransform();
- gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
-}
-"""
-
-def main():
- w = 640
- h = 480
- gl = OsContext(w, h, typ=GL_FLOAT)
- gl.Viewport(0, 0, w, h)
-
- gl.MatrixMode(GL_PROJECTION)
- gl.LoadIdentity();
-
- 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_CULL_FACE)
- 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))
- 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)
-
- 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)
-
- im = gl.getImage()
- cv2.imshow('a', im)
- import pdb; pdb.set_trace()
-
-
-
-
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/contexts/fix_warnings.py b/contexts/fix_warnings.py
deleted file mode 100644
index 1ddf556..0000000
--- a/contexts/fix_warnings.py
+++ /dev/null
@@ -1,17 +0,0 @@
-def fix_warnings():
- import platform
- if platform.system() == 'Darwin':
- # Get rid of various flags that cause warnings and/or errors
- 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
diff --git a/everything.py b/everything.py
deleted file mode 100644
index fd652ba..0000000
--- a/everything.py
+++ /dev/null
@@ -1,29 +0,0 @@
-__all__ = []
-
-import camera
-from camera import *
-__all__ += camera.__all__
-
-import renderer
-from renderer import *
-__all__ += renderer.__all__
-
-import lighting
-from lighting import *
-__all__ += lighting.__all__
-
-import topology
-from topology import *
-__all__ += topology.__all__
-
-import geometry
-from geometry import *
-__all__ += geometry.__all__
-
-import serialization
-from serialization import *
-__all__ += serialization.__all__
-
-import filters
-from filters import *
-__all__ += filters.__all__
diff --git a/lighting.py b/lighting.py
deleted file mode 100755
index d1df3c6..0000000
--- a/lighting.py
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/usr/bin/env python
-# encoding: utf-8
-
-"""
-Author(s): Matthew Loper
-
-See LICENCE.txt for licensing and contact information.
-"""
-
-__all__ = ['LambertianPointLight', 'SphericalHarmonics']
-
-import os, sys, logging
-import numpy as np
-import scipy.sparse as sp
-import scipy
-
-from chumpy.utils import row, col
-import chumpy as ch
-from chumpy.ch import Ch
-from geometry import VertNormals
-from chumpy import multiply, maximum
-
-
-logger = logging.getLogger(__name__)
-
-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[:,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)
- return real_coeff
-
-
-
-class SphericalHarmonics(Ch):
- dterms = 'vn', 'components'
- terms = ['light_color']
-
- 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(5)/(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):
- 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.num_verts = self.sh_coeffs.shape[0]
-
- if 'light_color' in which or self.mtx.shape[1] != 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):
- 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
- comps = comps * self.K.ravel()
- if wrt is self.vn:
- vn = self.vn.r.reshape((-1,3))
-
- #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]
- VS1 = np.ones(self.sh_coeffs.shape[0]) * comps[3]
- #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[:,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]
-
- #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)
- 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):
- """
- :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.))
- 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
- result = result / v_distances ** 2.
- result = maximum(result, 0.0)
-
- return result
-
-
-
-
-
-class LambertianPointLight(Ch):
- terms = 'f', 'num_verts', 'light_color'
- 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 not hasattr(self, 'ldn'):
- 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)
- 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))
-
- if 'vc' in which:
- 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
-
- def compute_dr_wrt(self, wrt):
- if wrt is self._lpl:
- return 1
-
-
-
-# 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):
-
- 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()
-
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/__init__.py b/opendr/__init__.py
similarity index 60%
rename from __init__.py
rename to opendr/__init__.py
index 603eebe..b028a1b 100644
--- a/__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 = {}
@@ -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,10 +341,10 @@ 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 '- - - - - - - - - - - - - - - - - - - - - - -'
- 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/camera.py b/opendr/camera.py
similarity index 62%
rename from camera.py
rename to opendr/camera.py
index 3f9d651..1fc8671 100755
--- a/camera.py
+++ b/opendr/camera.py
@@ -9,83 +9,115 @@
__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
class RigidTransform(Ch):
+ # pylint: disable=attribute-defined-outside-init
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:
- 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))
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)
- data = np.vstack([rot for i in range(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 _ 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):
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.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()
+ 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.):
+ 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 # 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.
+ 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.squeeze()
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:
@@ -100,7 +132,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
@@ -108,14 +140,14 @@ 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)
- 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
- 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
@@ -129,53 +161,56 @@ 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))
-
- @depends_on('f','c')
+ 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):
- 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
def view_matrix(self):
R = cv2.Rodrigues(self.rt.r)[0]
return np.hstack((R, col(self.t.r)))
-
+
class ProjectPoints3D(ProjectPoints):
+ # pylint: disable=attribute-defined-outside-init
dterms = 'v', 'rt', 't', 'f', 'c', 'k'
def compute_r(self):
result = ProjectPoints.compute_r(self)
return np.hstack((result, col(self.z_coords.r)))
-
+
@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)
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:
bigger = np.zeros((result.shape[0]/2, 3, result.shape[1]))
@@ -184,23 +219,8 @@ 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]))
- 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()
-
+ return result
diff --git a/common.py b/opendr/common.py
similarity index 67%
rename from common.py
rename to opendr/common.py
index 1128216..6092f92 100755
--- a/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 *
+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.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)
- dx = np.concatenate((dx[:,1:,:], dx[:,:-1,:]), axis=3)
- dx = nanmean(dx, axis=3)
+ dy = np.concatenate((dy[1:, :, :], dy[:-1, :, :]), axis=3)
+ dy = np.nanmean(dy, axis=3)
+ dx = np.concatenate((dx[:, 1:, :], dx[:, :-1, :]), axis=3)
+ dx = np.nanmean(dx, axis=3)
if arr.shape[2] > 1:
gy, gx, _ = np.gradient(arr)
@@ -40,8 +29,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
@@ -49,7 +38,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]
@@ -68,13 +57,13 @@ 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
+ bnd_nan.ravel()[bnd_nan.ravel() > 0] = np.nan
bnd_nan += 1
obs_nonbnd = np.atleast_3d(observed) * bnd_nan
@@ -90,7 +79,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
@@ -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
@@ -167,9 +155,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)
@@ -182,7 +170,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]
@@ -201,8 +189,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 +207,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)
@@ -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]))
+ 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
@@ -248,7 +235,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))
@@ -272,7 +259,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))
@@ -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))
@@ -306,12 +293,12 @@ 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)])
- 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))
@@ -321,22 +308,37 @@ def dr_wrt_vc(visible, visibility, f, barycentric, frustum, vc_size, num_channel
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
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)
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
@@ -344,15 +346,14 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None):
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)
@@ -362,29 +363,29 @@ def draw_visibility_image(gl, v, f, boundarybool_image=None):
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);
- verts_by_face = np.asarray(v.reshape((-1,3))[f.ravel()], dtype=np.float64, order='C')
+ 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:
@@ -393,19 +394,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
@@ -413,7 +414,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())
@@ -424,12 +425,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)
+ # 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:
@@ -437,19 +438,34 @@ 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
-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)
@@ -458,51 +474,50 @@ def draw_barycentric_image(gl, v, f, boundarybool_image=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
# 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/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 51%
rename from contexts/autogen.py
rename to opendr/contexts/autogen.py
index 502404e..f55fd8d 100755
--- a/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))
@@ -147,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
@@ -157,4 +154,3 @@ def main():
if __name__ == '__main__':
main()
-
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/opendr/contexts/draw_triangle_shaders_2_1.py b/opendr/contexts/draw_triangle_shaders_2_1.py
new file mode 100644
index 0000000..260d700
--- /dev/null
+++ b/opendr/contexts/draw_triangle_shaders_2_1.py
@@ -0,0 +1,79 @@
+__author__ = 'matt'
+
+import platform
+import cv2
+import numpy as np
+from opendr.contexts._constants import * # pylint: disable=wildcard-import, unused-wildcard-import
+
+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
+
+fs_source = """
+#version 120
+
+void main(void) {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+"""
+
+vs_source = """
+#version 120
+void main(void) {
+ //gl_Position = ftransform();
+ gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
+}
+"""
+
+def main():
+ w = 640
+ h = 480
+ gl = OsContext(w, h, typ=GL_FLOAT)
+ gl.Viewport(0, 0, w, h)
+
+ gl.MatrixMode(GL_PROJECTION)
+ gl.LoadIdentity()
+
+ 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_CULL_FACE)
+ 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))
+ f = np.arange(v.size, dtype=np.uint32)
+ gl.EnableClientState(GL_VERTEX_ARRAY)
+ gl.VertexPointer(v)
+
+ 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))
+
+
+ gl.DrawElements(GL_TRIANGLES, f)
+
+ im = gl.getImage()
+ cv2.imshow('a', im)
+ # import pdb; pdb.set_trace()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/contexts/draw_triangle_shaders_3_2.py b/opendr/contexts/draw_triangle_shaders_3_2.py
similarity index 80%
rename from contexts/draw_triangle_shaders_3_2.py
rename to opendr/contexts/draw_triangle_shaders_3_2.py
index 05e994e..b93bca8 100644
--- a/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)
###############################
@@ -138,12 +138,8 @@ def main():
im = gl.getImage()
cv2.imshow('a', im)
print gl.GetError()
- import pdb; pdb.set_trace()
-
-
-
-
+ # 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
new file mode 100644
index 0000000..8d69fa2
--- /dev/null
+++ b/opendr/contexts/fix_warnings.py
@@ -0,0 +1,17 @@
+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():
+ 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/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 60%
rename from cvwrap.py
rename to opendr/cvwrap.py
index b6e38e4..7d5e392 100644
--- a/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/dummy.py b/opendr/dummy.py
similarity index 74%
rename from dummy.py
rename to opendr/dummy.py
index 4005759..28c0712 100755
--- a/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
new file mode 100644
index 0000000..725394e
--- /dev/null
+++ b/opendr/everything.py
@@ -0,0 +1,29 @@
+__all__ = []
+
+import opendr.camera
+from opendr.camera import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.camera.__all__
+
+import opendr.renderer
+from opendr.renderer import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.renderer.__all__
+
+import opendr.lighting
+from opendr.lighting import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.lighting.__all__
+
+import opendr.topology
+from opendr.topology import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.topology.__all__
+
+import opendr.geometry
+from opendr.geometry import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.geometry.__all__
+
+import opendr.serialization
+from opendr.serialization import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.serialization.__all__
+
+import opendr.filters
+from opendr.filters import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.filters.__all__
diff --git a/filters.py b/opendr/filters.py
similarity index 76%
rename from filters.py
rename to opendr/filters.py
index bba0b92..1f7c911 100755
--- a/filters.py
+++ b/opendr/filters.py
@@ -8,55 +8,53 @@
__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):
-
- blur_mtx = filter_for(imshape[0], imshape[1], imshape[2] if len(imshape)>2 else 1, kernel = GaussianKernel2D(3, 1))
+ 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))
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)
+ 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
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
@@ -66,103 +64,105 @@ 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):
- cur_obj = GaussPyrDownOne(px=cur_obj, im_shape = cur_imshape)
+ 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)
+ 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')
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
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))
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'
+ # pylint: disable=attribute-defined-outside-init
+ 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()
+ 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 = shape[0]
- w = shape[1]
- d = shape[2] if len(shape) > 2 else 1
-
- JS = np.arange(h*w*d).reshape((h,w,d))
- JS = JS[::2,::2,:]
+ 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()
@@ -175,8 +175,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()
@@ -189,7 +189,6 @@ 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)
@@ -204,42 +203,42 @@ 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), (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 = []
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)]
@@ -247,18 +246,6 @@ 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()
+ return sp.csc_matrix((data, (IS, JS)), shape=(h*w*d, h*w*d))
diff --git a/geometry.py b/opendr/geometry.py
similarity index 61%
rename from geometry.py
rename to opendr/geometry.py
index a30365c..844e9a7 100755
--- a/geometry.py
+++ b/opendr/geometry.py
@@ -9,78 +9,78 @@
__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.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)
+ blocks[:, i, i] += self.s_inv
+
+ 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):
+ # 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,43 +90,44 @@ 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)
+ 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
+ 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)
+ 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:
@@ -138,49 +139,50 @@ 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)
-
+
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))
-
+ 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 = []
for i in range(v.size/3):
@@ -195,64 +197,69 @@ 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.
+ 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):
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."""
-
+ # pylint: disable=unnecessary-lambda
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
-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)
+ nm = lambda x: NormalizedNx3(x)
else:
- nm = lambda x : x
+ nm = lambda x: x
+
+ 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
- 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, access-member-before-definition
+
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
-
+
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
@@ -270,24 +277,24 @@ 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:
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))
+ 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:
return self.normals.dr_wrt(wrt)
@@ -295,14 +302,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'
@@ -314,40 +322,41 @@ 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]
- 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, access-member-before-definition
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 +364,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:
@@ -397,18 +406,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 +426,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
@@ -430,17 +439,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
new file mode 100755
index 0000000..bdb40fc
--- /dev/null
+++ b/opendr/lighting.py
@@ -0,0 +1,244 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+"""
+Author(s): Matthew Loper
+
+See LICENCE.txt for licensing and contact information.
+"""
+
+__all__ = ['LambertianPointLight', 'SphericalHarmonics']
+
+import logging
+import numpy as np
+import scipy.sparse as sp
+import chumpy as ch
+from chumpy.utils import row, col
+from chumpy.ch import Ch
+from chumpy import multiply, maximum
+from opendr.geometry import VertNormals
+
+
+logger = logging.getLogger(__name__)
+
+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[:, 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)
+ return real_coeff
+
+
+
+class SphericalHarmonics(Ch):
+ # pylint: disable=attribute-defined-outside-init
+ dterms = 'vn', 'components'
+ terms = ['light_color']
+
+ 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(5)/(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): # pylint: disable=arguments-differ
+ 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.num_verts = self.sh_coeffs.shape[0]
+
+ 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)
+ 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
+ comps = comps * self.K.ravel()
+ if wrt is self.vn:
+ vn = self.vn.r.reshape((-1, 3))
+
+ #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]
+ VS1 = np.ones(self.sh_coeffs.shape[0]) * comps[3]
+ #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[:, 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]
+
+ #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)
+ 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, 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 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 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)
+ light_pos = rot.T.dot(light_pos-camera_t)
+ light_dir = rot.T.dot(light_dir)
+
+ 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(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'
+ result = light_dot_normal.ravel() * cosangle.ravel()**spot_exponent
+ result = result / v_distances ** 2.
+ result = maximum(result, 0.0)
+
+ return result
+
+
+
+
+
+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): # pylint: disable=arguments-differ
+ 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:
+ self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0))
+ if not hasattr(self, 'ldn'):
+ 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)
+ 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)
+ 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))
+
+ if 'vc' in which:
+ 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
+
+ def compute_dr_wrt(self, wrt):
+ if wrt is self._lpl:
+ return 1
+
+
+# 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():
+
+ 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))))
diff --git a/renderer.py b/opendr/renderer.py
similarity index 64%
rename from renderer.py
rename to opendr/renderer.py
index 59cfe86..2fead21 100755
--- a/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 *
-from contexts._constants 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
@@ -57,7 +55,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):
@@ -87,34 +86,35 @@ def fpe(self):
class DepthRenderer(BaseRenderer):
- terms = 'f', 'frustum', 'background_image','overdraw'
- dterms = 'camera', 'v'
-
+ # 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):
-
+
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
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)
@@ -133,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']
@@ -160,16 +160,16 @@ 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)
+
+ assert self.v is self.camera.v
@depends_on(dterms+terms)
@@ -177,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)
@@ -192,61 +192,93 @@ 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
+ @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)
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:])
+ 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):
if wrt is not self.camera:
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)
- def on_changed(self, which):
+ 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): # pylint: disable=arguments-differ
if 'frustum' in which:
w = self.frustum['width']
h = self.frustum['height']
@@ -254,78 +286,77 @@ 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()
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'
+ 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)
+ 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):
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)
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 = 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)
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
@@ -335,20 +366,21 @@ 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
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]
@@ -356,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
@@ -400,20 +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)
+ return draw_boundary_images(self.glf, 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)
-
-
-
class TexturedRenderer(ColoredRenderer):
+ # pylint: disable=attribute-defined-outside-init
terms = 'f', 'frustum', 'vt', 'ft', 'background_image', 'overdraw'
dterms = 'vc', 'camera', 'bgcolor', 'texture_image'
@@ -422,12 +451,12 @@ 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):
return 3
-
+
def release_textures(self):
if hasattr(self, 'textureID'):
arr = np.asarray(np.array([self.textureID]), np.uint32)
@@ -436,7 +465,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)
@@ -447,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))
@@ -463,10 +487,10 @@ 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):
+ 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
@@ -474,7 +498,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]
@@ -489,31 +513,31 @@ 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
-
+
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)
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)
@@ -525,39 +549,39 @@ 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()
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
@@ -566,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
@@ -578,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
@@ -598,100 +622,97 @@ 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)
-
+
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
+ 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):
+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
+ silhouette_edges, _ = 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)
- 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):
@@ -702,8 +723,8 @@ def setup_camera(gl, camera, frustum):
frustum['near'], frustum['far'],
camera.view_matrix,
camera.k.r)
-
-
+
+
vs_source = """
#version 120
@@ -788,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')
@@ -808,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'):
@@ -843,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/rogrenderer.py b/opendr/rogrenderer.py
similarity index 56%
rename from rogrenderer.py
rename to opendr/rogrenderer.py
index 07f7070..2c175b3 100644
--- a/rogrenderer.py
+++ b/opendr/rogrenderer.py
@@ -4,80 +4,83 @@
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)
- im = np.asarray(im, np.float64)/255.
+ 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
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
-
+ 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():
+def load_basics():
+ from opendr.test_renderer import getcam
+ from opendr.util_tests import get_earthmesh
+ from opendr.lighting import LambertianPointLight
+
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,
- 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.])
+
+ 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__':
-
+
+
+def main():
import matplotlib.pyplot as plt
- mesh, lighting, camera, frustum, renderers = load_basics()
+ _, _, _, _, renderers = load_basics()
plt.ion()
# Show default textured renderer
@@ -85,9 +88,12 @@ 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())
plt.imshow(r2)
- import pdb; pdb.set_trace()
+ # import pdb; pdb.set_trace()
+
+if __name__ == '__main__':
+ main()
diff --git a/serialization.py b/opendr/serialization.py
similarity index 94%
rename from serialization.py
rename to opendr/serialization.py
index 8b51a5d..01e5d81 100644
--- a/serialization.py
+++ b/opendr/serialization.py
@@ -9,13 +9,13 @@
__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):
- 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:
@@ -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
new file mode 100644
index 0000000..40df5e5
--- /dev/null
+++ b/opendr/simple.py
@@ -0,0 +1,36 @@
+__all__ = []
+
+import opendr.camera
+from opendr.camera import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.camera.__all__
+
+import opendr.renderer
+from opendr.renderer import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.renderer.__all__
+
+import opendr.lighting
+from opendr.lighting import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.lighting.__all__
+
+import opendr.topology
+from opendr.topology import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.topology.__all__
+
+import opendr.geometry
+from opendr.geometry import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.geometry.__all__
+
+import opendr.serialization
+from opendr.serialization import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.serialization.__all__
+
+import opendr.utils
+from opendr.utils import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.utils.__all__
+
+import opendr.filters
+from opendr.filters import * # pylint: disable=wildcard-import, unused-wildcard-import
+__all__ += opendr.filters.__all__
+
+import chumpy as ch # pylint: disable=unused-import
+__all__ += ['ch']
diff --git a/slider_demo.py b/opendr/slider_demo.py
similarity index 79%
rename from slider_demo.py
rename to opendr/slider_demo.py
index 2498512..750e0bd 100644
--- a/slider_demo.py
+++ b/opendr/slider_demo.py
@@ -1,35 +1,33 @@
-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 *
+ from opendr.everything import load_mesh, TexturedRenderer, ProjectPoints, SphericalHarmonics, VertNormals
# 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)
cv2.namedWindow('image')
cv2.namedWindow('derivatives')
@@ -48,40 +46,39 @@ 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)
+ while True:
+ cv2.imshow('image', rn.r)
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]:
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)
# 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
# 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
- #
+ #
# 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 +89,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/test_camera.py b/opendr/test_camera.py
similarity index 63%
rename from test_camera.py
rename to opendr/test_camera.py
index 63178f9..531bd42 100755
--- a/test_camera.py
+++ b/opendr/test_camera.py
@@ -8,43 +8,52 @@
import unittest
import numpy as np
-
-from camera import *
import chumpy as ch
-
-
+from opendr.camera import ProjectPoints, ProjectPoints3D
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}
return cam_params
-
+
+ def test_project_points_without_derivatives(self):
+ 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]))
+
+ 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()) # FIXME pylint: disable=unsubscriptable-object
+
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)
@@ -54,33 +63,28 @@ 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 '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)
-
+
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)
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/test_depth_renderer.py b/opendr/test_depth_renderer.py
similarity index 63%
rename from test_depth_renderer.py
rename to opendr/test_depth_renderer.py
index de7fffb..5266e3c 100644
--- a/test_depth_renderer.py
+++ b/opendr/test_depth_renderer.py
@@ -1,32 +1,31 @@
-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 = 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))
-
+
# import time
# tm = time.time()
# rn.r
@@ -35,27 +34,20 @@ 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
- 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))
+ 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))
- if visualize:
+ if self.VISUALIZE:
import matplotlib.pyplot as plt
plt.figure()
for which in range(3):
@@ -74,33 +66,27 @@ def test_derivatives(self):
self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .031)
- if visualize:
- plt.subplot(2,3,which+1)
+ if self.VISUALIZE:
+ 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):
- 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))
+ 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))
- if visualize:
+ if self.VISUALIZE:
import matplotlib.pyplot as plt
plt.ion()
plt.figure()
@@ -120,21 +106,19 @@ def test_derivatives2(self):
self.assertLess(np.mean(np.abs(dr_pred-dr_emp)), .024)
- if visualize:
- plt.subplot(2,3,which+1)
+ if self.VISUALIZE:
+ 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()
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()
diff --git a/test_geometry.py b/opendr/test_geometry.py
similarity index 51%
rename from test_geometry.py
rename to opendr/test_geometry.py
index 0a524c5..b9a3887 100755
--- a/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))
-
- 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)
-
-
+ empirical_diff = (vn2.r - vn1.r).reshape((-1, 3))
-suite = unittest.TestLoader().loadTestsFromTestCase(TestGeometry)
+ predicted_diff = dr_predicted.dot(eps.flatten()).reshape((-1, 3))
-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/test_renderer.py b/opendr/test_renderer.py
similarity index 76%
rename from test_renderer.py
rename to opendr/test_renderer.py
index c079222..a98598b 100755
--- a/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 *
-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),
@@ -80,11 +75,11 @@ 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 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:
@@ -93,25 +88,22 @@ 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
- 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,10 +173,10 @@ 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.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},
@@ -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,36 +235,36 @@ 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()
self.assertLess(meanerror, info['meannz'])
self.assertLess(mederror, info['mednz'])
-
+
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,17 +272,17 @@ 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)
renderer.set(vc=lighting)
# Get pixels and derivatives
- r = renderer.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 +293,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 +302,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
@@ -320,30 +310,30 @@ 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()
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()
-
+
+ mesh, lightings, camera, _, renderers = self.load_basics()
+
for renderer in renderers:
@@ -351,32 +341,32 @@ 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)
-
- 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.)
+ 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
-
+
# 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)
@@ -387,51 +377,51 @@ 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)
-
-
-
+
+
+
def test_color_derivatives(self):
-
- mesh, lightings, camera, frustum, renderers = self.load_basics()
-
+
+ mesh, lightings, camera, _, 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 '-------------------------------------------'
#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,39 +449,36 @@ 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)
-
+
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
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
new file mode 100755
index 0000000..b702a01
--- /dev/null
+++ b/opendr/test_sh.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+Author(s): Matthew Loper
+
+See LICENCE.txt for licensing and contact information.
+"""
+
+import unittest
+import numpy as np
+from chumpy import Ch
+from chumpy.utils import row, col
+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
+
+
+def getcam():
+ from opendr.camera import ProjectPoints3D
+
+ w = 640
+ h = 320
+
+ f = np.array([500, 500])
+ rt = np.zeros(3)
+ t = np.zeros(3)
+ k = np.zeros(5)
+ c = np.array([w/2., h/2.])
+ near = .1
+ far = 20.
+
+ frustum = {'near': near, 'far': far, 'width': w, 'height': h}
+ pp = ProjectPoints3D(f=f, rt=rt, t=t, k=k, c=c)
+
+ return pp, frustum
+
+
+
+class TestSphericalHarmonics(unittest.TestCase):
+ VISUALIZE = False
+
+ def test_spherical_harmonics(self):
+ if self.VISUALIZE:
+ plt.ion()
+
+ # Get mesh
+ v, f = get_sphere_mesh()
+
+ from opendr.geometry import VertNormals
+ vn = VertNormals(v=v, f=f)
+ #vn = Ch(mesh.estimate_vertex_normals())
+
+ # Get camera
+ cam, frustum = getcam()
+
+ # Get renderer
+ from opendr.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]))
+
+ cr.vc = sh_red + sh_green
+
+ ims_baseline = []
+ for comp_idx, subplot_idx in enumerate([3, 7, 8, 9, 11, 12, 13, 14, 15]):
+
+ sh_comps = np.zeros(9)
+ sh_comps[comp_idx] = 1
+ sh_red.components = Ch(sh_comps)
+ sh_green.components = Ch(-sh_comps)
+
+ newim = cr.r.reshape((frustum['height'], frustum['width'], 3))
+ ims_baseline.append(newim)
+
+ if 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
+ vn_shifted = (vn.r + offset)
+ vn_shifted = vn_shifted / col(np.sqrt(np.sum(vn_shifted**2, axis=1)))
+ vn_shifted = vn_shifted.ravel()
+ vn_shifted[vn_shifted > 1.] = 1
+ vn_shifted[vn_shifted < -1.] = -1
+ vn_shifted = Ch(vn_shifted)
+ cr.replace(sh_red.vn, vn_shifted)
+ 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 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 _ in range(3):
+ mtx, f = loop_subdivider(v, f)
+ v = mtx.dot(v.ravel()).reshape((-1, 3))
+ v /= 200.
+ v[:, 2] += 2
+
+ return v, f
+
+
+if __name__ == '__main__':
+ TestSphericalHarmonics.VISUALIZE = True
+ plt.ion()
+ suite = unittest.TestLoader().loadTestsFromTestCase(TestSphericalHarmonics)
+ unittest.TextTestRunner(verbosity=2).run(suite)
+ plt.show()
diff --git a/topology.py b/opendr/topology.py
similarity index 56%
rename from topology.py
rename to opendr/topology.py
index fa52d96..058415a 100644
--- a/topology.py
+++ b/opendr/topology.py
@@ -8,25 +8,23 @@
__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
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)))
+ 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
@@ -78,86 +76,84 @@ 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)
-
- if True:
- # New values for each vertex
- for idx in xrange(len(mesh_v)):
-
- # find neighboring vertices
- nbrs = np.nonzero(vc[:,idx])[0]
-
- 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)
-
- JS.append(idx)
- IS.append(idx)
- data.append(1. - (wt * nn))
+ vo = get_vert_opposites_per_edge(mesh_f)
+
+ # New values for each vertex
+ for idx in xrange(len(mesh_v)):
+
+ # find neighboring vertices
+ nbrs = np.nonzero(vc[:, idx])[0]
+
+ 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)
+
+ 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)
-
- opposites = vo[(vsl[0], vsl[1])]
- for opp in opposites:
- IS.append(start + idx)
- JS.append(opp)
- data.append(2./8./len(opposites))
+ 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 = []
- 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):
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))
@@ -165,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:
@@ -183,5 +179,3 @@ def get_vert_opposites_per_edge(mesh_v, mesh_f):
else:
result[key] = [val]
return result
-
-
diff --git a/util_tests.py b/opendr/util_tests.py
similarity index 85%
rename from util_tests.py
rename to opendr/util_tests.py
index d10b6ad..0ed3354 100644
--- a/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)
diff --git a/utils.py b/opendr/utils.py
similarity index 63%
rename from utils.py
rename to opendr/utils.py
index 5ef77a3..c54fa58 100644
--- a/utils.py
+++ b/opendr/utils.py
@@ -24,7 +24,13 @@ 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)
+ source.close()
except:
- raise Exception('Unable to get url: %s' % (url,))
- open(dest_fname, 'w').write(contents)
+ raise Exception('Unable to get url: %s' % (url, ))
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.txt b/requirements.txt
index 4402122..3b0206d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,4 @@
-
--e .
+cython>=0.24
+numpy>=1.10.1
+matplotlib>=1.5.0
+chumpy>=0.67.4
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 e55e6c5..620fa1a 100644
--- a/setup.py
+++ b/setup.py
@@ -4,12 +4,20 @@
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:
from Cython.Build import cythonize
@@ -18,42 +26,62 @@
cythonize = lambda x : x
have_cython = False
+context_dir = os.path.join(os.path.dirname(__file__), 'opendr', 'contexts')
-# 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__
+osmesa_mirrors = [
+ 'https://s3.amazonaws.com/bodylabs-assets/public/osmesa/',
+ 'http://files.is.tue.mpg.de/mloper/opendr/osmesa/',
+]
+# Filenames on the above mirrors follow this convention:
+sysinfo = platform.uname()
+osmesa_fname = 'OSMesa.%s.%s.zip' % (sysinfo[0], sysinfo[-2])
-context_dir = os.path.join(os.path.dirname(__file__), 'contexts')
+install_requires = parse_requirements('requirements.txt', session=False)
+install_requires = [str(ir.req) for ir in install_requires]
-def download_osmesa():
- import os, re, zipfile
- from utils import wget
- mesa_dir = os.path.join(context_dir,'OSMesa')
+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 opendr.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):
- print "Downloading %s" % osmesa_fname
- # MPI url: http://files.is.tue.mpg.de/mloper/opendr/osmesa/%s
- # BL url: https://s3.amazonaws.com/bodylabs-assets/public/osmesa/%s
- wget('http://files.is.tue.mpg.de/mloper/opendr/osmesa/%s' % (osmesa_fname,), dest_fname=zip_fname)
+ 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
+ from opendr.contexts import autogen
autogen.main()
for x in sources:
assert(os.path.exists(x))
@@ -65,15 +93,14 @@ 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*']},
- install_requires=['Cython', 'chumpy >= 0.58', 'matplotlib'],
+ # package_data={'opendr': ['test_dr/nasa*']},
+ install_requires=install_requires,
description='opendr',
ext_modules=ext_modules,
license='MIT',
@@ -113,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/simple.py b/simple.py
deleted file mode 100644
index 3fee5e1..0000000
--- a/simple.py
+++ /dev/null
@@ -1,38 +0,0 @@
-__all__ = []
-
-import camera
-from camera import *
-__all__ += camera.__all__
-
-import renderer
-from renderer import *
-__all__ += renderer.__all__
-
-import lighting
-from lighting import *
-__all__ += lighting.__all__
-
-import topology
-from topology import *
-__all__ += topology.__all__
-
-import geometry
-from geometry import *
-__all__ += geometry.__all__
-
-import serialization
-from serialization import *
-__all__ += serialization.__all__
-
-import utils
-from utils import *
-__all__ += utils.__all__
-
-import filters
-from filters import *
-__all__ += filters.__all__
-
-import chumpy as ch
-__all__ += ['ch']
-
-
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
diff --git a/test_sh.py b/test_sh.py
deleted file mode 100755
index 6b789e1..0000000
--- a/test_sh.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python
-# encoding: utf-8
-"""
-Author(s): Matthew Loper
-
-See LICENCE.txt for licensing and contact information.
-"""
-
-from chumpy import Ch
-import numpy as np
-from chumpy.utils import row, col
-from lighting import SphericalHarmonics
-import unittest
-try:
- import matplotlib.pyplot as plt
-except:
- from dummy import dummy as plt
-from topology import loop_subdivider
-
-visualize = False
-
-def getcam():
- from camera import ProjectPoints3D
-
- w = 640
- h = 320
-
- f = np.array([500,500])
- rt = np.zeros(3)
- t = np.zeros(3)
- k = np.zeros(5)
- c = np.array([w/2., h/2.])
- near = .1
- far = 20.
-
- frustum = {'near': near, 'far': far, 'width': w, 'height': h}
- pp = ProjectPoints3D(f=f, rt=rt, t=t, k=k, c=c)
-
- return pp, frustum
-
-
-
-class TestSphericalHarmonics(unittest.TestCase):
-
- def test_spherical_harmonics(self):
- global visualize
- if visualize:
- plt.ion()
-
- # Get mesh
- v, f = get_sphere_mesh()
-
- from geometry import VertNormals
- vn = VertNormals(v=v, f=f)
- #vn = Ch(mesh.estimate_vertex_normals())
-
- # 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]))
-
- cr.vc = sh_red + sh_green
-
- ims_baseline = []
- for comp_idx, subplot_idx in enumerate([3,7,8,9,11,12,13,14,15]):
-
- sh_comps = np.zeros(9)
- sh_comps[comp_idx] = 1
- sh_red.components = Ch(sh_comps)
- sh_green.components = Ch(-sh_comps)
-
- newim = cr.r.reshape((frustum['height'], frustum['width'], 3))
- ims_baseline.append(newim)
-
- if visualize:
- plt.subplot(3,5,subplot_idx)
- plt.imshow(newim)
- plt.axis('off')
-
- offset = row(.4 * (np.random.rand(3)-.5))
- #offset = row(np.array([1.,1.,1.]))*.05
- vn_shifted = (vn.r + offset)
- vn_shifted = vn_shifted / col(np.sqrt(np.sum(vn_shifted**2, axis=1)))
- vn_shifted = vn_shifted.ravel()
- vn_shifted[vn_shifted>1.] = 1
- vn_shifted[vn_shifted<-1.] = -1
- vn_shifted = Ch(vn_shifted)
- cr.replace(sh_red.vn, vn_shifted)
- if True:
- for comp_idx in range(9):
- if visualize:
- plt.figure(comp_idx+2)
-
- sh_comps = np.zeros(9)
- sh_comps[comp_idx] = 1
- sh_red.components = Ch(sh_comps)
- sh_green.components = Ch(-sh_comps)
-
- pred = cr.dr_wrt(vn_shifted).dot(col(vn_shifted.r.reshape(vn.r.shape) - vn.r)).reshape((frustum['height'], frustum['width'], 3))
- if visualize:
- plt.subplot(1,2,1)
- plt.imshow(pred)
- plt.title('pred (comp %d)' % (comp_idx,))
- plt.subplot(1,2,2)
-
- newim = cr.r.reshape((frustum['height'], frustum['width'], 3))
- emp = newim - ims_baseline[comp_idx]
- if visualize:
- plt.imshow(emp)
- plt.title('empirical (comp %d)' % (comp_idx,))
- pred_flat = pred.ravel()
- emp_flat = emp.ravel()
- nnz = np.unique(np.concatenate((np.nonzero(pred_flat)[0], np.nonzero(emp_flat)[0])))
-
- if comp_idx != 0:
- med_diff = np.median(np.abs(pred_flat[nnz]-emp_flat[nnz]))
- med_obs = np.median(np.abs(emp_flat[nnz]))
- if comp_idx == 4 or comp_idx == 8:
- self.assertTrue(med_diff / med_obs < .6)
- else:
- self.assertTrue(med_diff / med_obs < .3)
- if visualize:
- plt.axis('off')
-
-
-def get_sphere_mesh():
- 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
-
- for i in range(3):
- mtx, f = loop_subdivider(v, f)
- v = mtx.dot(v.ravel()).reshape((-1,3))
- v /= 200.
- v[:,2] += 2
-
- return v, f
-
-
-
-
-if __name__ == '__main__':
- visualize = True
- plt.ion()
- #unittest.main()
- suite = unittest.TestLoader().loadTestsFromTestCase(TestSphericalHarmonics)
- unittest.TextTestRunner(verbosity=2).run(suite)
- plt.show()
- import pdb; pdb.set_trace()
-