示例#1
0
    def test_reading_obj_with_mtl_from_sc_file(self, mock_sc, mock_s3_open):
        from baiji.pod.asset_cache import CacheFile

        sc_obj_with_texure = self.obj_with_texure.replace(
            "s3://bodylabs-korper-assets", '')
        sc_obj_with_texure_mtl = self.obj_with_texure_mtl.replace(
            "s3://bodylabs-korper-assets", '')
        sc_obj_with_texure_tex = self.obj_with_texure_tex.replace(
            "s3://bodylabs-korper-assets", '')
        bucket = "bodylabs-korper-assets"

        m = obj.load(sc(sc_obj_with_texure, bucket=bucket))

        mock_sc.assert_has_calls([
            mock.call(sc_obj_with_texure, bucket=bucket),  # the one above
            mock.call(
                CacheFile(sc, sc_obj_with_texure_mtl,
                          bucket=bucket).local),  # in obj.load
            mock.call(
                CacheFile(sc, sc_obj_with_texure_tex,
                          bucket=bucket).local),  # in obj.load
        ])
        mock_s3_open.assert_has_calls([
            mock.call(sc(sc_obj_with_texure, bucket=bucket), 'rb'),
            mock.call(sc(sc_obj_with_texure_mtl, bucket=bucket), 'r'),
        ])
        self.assertEqual(m.materials_filepath,
                         sc(sc_obj_with_texure_mtl, bucket=bucket))
        self.assertEqual(m.texture_filepath,
                         sc(sc_obj_with_texure_tex, bucket=bucket))
示例#2
0
 def setUp(self):
     self.test_wrl_url = "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_wrl.wrl"
     self.test_wrl_path = sc(self.test_wrl_url)
     self.test_obj_url = "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_box.obj"
     self.test_wrl_converted_path = sc(
         "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_wrl_converted.obj"
     )
示例#3
0
 def setUp(self):
     import tempfile
     from lace.cache import sc
     self.tmp_dir = tempfile.mkdtemp('bodylabs-test')
     self.truth = {
         'box_v':
         np.array([[0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, -0.5],
                   [0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5],
                   [0.5, 0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5]]).T,
         'box_f':
         np.array([[0, 1, 2], [3, 2, 1], [0, 2, 4], [6, 4, 2], [0, 4, 1],
                   [5, 1, 4], [7, 5, 6], [4, 6, 5], [7, 6, 3], [2, 3, 6],
                   [7, 3, 5], [1, 5, 3]]),
         'box_segm': {
             'a': np.array(range(6), dtype=np.uint32),
             'b': np.array([6, 10, 11], dtype=np.uint32),
             'c': np.array([7, 8, 9], dtype=np.uint32)
         },
         'landm': {
             'pospospos': 0,
             'negnegneg': 7
         },
         'landm_xyz': {
             'pospospos': np.array([0.5, 0.5, 0.5]),
             'negnegneg': np.array([-0.5, -0.5, -0.5])
         },
     }
     self.test_ply_url = "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_box.ply"
     self.test_ply_path = sc(self.test_ply_url)
     self.test_bin_ply_path = sc(
         "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_box_le.ply"
     )
     self.test_pp_path = sc(
         "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_box.pp"
     )
示例#4
0
 def load_texture(self, texture_version):
     '''
     Expect a texture version number as an integer, load the texture version from /is/ps/shared/data/body/template/texture_coordinates/.
     Currently there are versions [0, 1, 2, 3] availiable.
     '''
     import numpy as np
     lowres_tex_template = 's3://bodylabs-korper-assets/is/ps/shared/data/body/template/texture_coordinates/textured_template_low_v%d.obj' % texture_version
     highres_tex_template = 's3://bodylabs-korper-assets/is/ps/shared/data/body/template/texture_coordinates/textured_template_high_v%d.obj' % texture_version
     from lace.mesh import Mesh
     from lace.cache import sc
     mesh_with_texture = Mesh(filename=sc(lowres_tex_template))
     if not np.all(mesh_with_texture.f.shape == self.f.shape):
         mesh_with_texture = Mesh(filename=sc(highres_tex_template))
     self.transfer_texture(mesh_with_texture)
示例#5
0
    def test_reading_obj_with_mtl_from_missing_windows_absolute_path(
            self, mock_s3_open):
        # In this case, we're given a windows absolute path, which it totally wrong, but if there happens
        # to be a mtl file of the right name in the same dir as the obj, go for it.
        # This is a signiicant case, because 3dMD outputs mtllib this way.
        skip_if_unavailable('s3')
        obj_path = os.path.join(self.scratch_dir,
                                'abs_path_to_missing_windows_mtl.obj')
        real_mlt_path = os.path.join(self.scratch_dir,
                                     'abs_path_to_missing_windows_mtl.mlt')
        arbitrary_mlt_path = 'C:/Users/ARGH/Documents/I-Did_some_scans/Subject_47/abs_path_to_missing_windows_mtl.mlt'
        tex_path = os.path.abspath(sc(self.obj_with_texure_tex))

        with open(obj_path, 'w') as f:
            f.write('mtllib {}\n'.format(arbitrary_mlt_path))
        with open(real_mlt_path, 'w') as f:
            f.write('map_Ka {}\n'.format(tex_path))

        m = obj.load(obj_path)

        mock_s3_open.assert_has_calls([
            mock.call(obj_path, 'rb'),
            mock.call(real_mlt_path, 'r'),
        ])
        self.assertEqual(m.materials_filepath, real_mlt_path)
        self.assertEqual(m.texture_filepath, tex_path)
示例#6
0
 def test_writing_obj_with_mtl(self):
     local_file = os.path.join(self.tmp_dir,
                               "test_writing_obj_with_mtl.obj")
     m = obj.load(sc(self.obj_with_texure))
     obj.dump(m, local_file)
     self.assertTrue(s3.exists(os.path.splitext(local_file)[0] + '.mtl'))
     self.assertTrue(s3.exists(os.path.splitext(local_file)[0] + '.png'))
示例#7
0
    def test_reading_obj_with_mtl_from_missing_absolute_path(
            self, mock_s3_open):
        # If an absolute path is given and the file is missing, try looking in the same directory;
        # this lets you find the most common intention when an abs path is used.
        skip_if_unavailable('s3')
        obj_path = os.path.join(self.scratch_dir,
                                'abs_path_to_missing_mtl.obj')
        real_mlt_path = os.path.join(self.scratch_dir,
                                     'abs_path_to_missing_mtl.mlt')
        arbitrary_mlt_path = os.path.join(self.scratch_dir,
                                          'some_other_absolute_path',
                                          'abs_path_to_missing_mtl.mlt')
        tex_path = os.path.abspath(sc(self.obj_with_texure_tex))

        with open(obj_path, 'w') as f:
            f.write('mtllib {}\n'.format(arbitrary_mlt_path))
        with open(real_mlt_path, 'w') as f:
            f.write('map_Ka {}\n'.format(tex_path))

        m = obj.load(obj_path)

        mock_s3_open.assert_has_calls([
            mock.call(obj_path, 'rb'),
            mock.call(real_mlt_path, 'r'),
        ])
        self.assertEqual(m.materials_filepath, real_mlt_path)
        self.assertEqual(m.texture_filepath, tex_path)
示例#8
0
    def test_reading_obj_with_mtl_from_local_file(self, mock_s3_open):
        local_obj_with_texure = os.path.join(
            self.tmp_dir, os.path.basename(self.obj_with_texure))
        local_obj_with_texure_mtl = os.path.join(
            self.tmp_dir, os.path.basename(self.obj_with_texure_mtl))
        local_obj_with_texure_tex = os.path.join(
            self.tmp_dir, os.path.basename(self.obj_with_texure_tex))
        s3.cp(sc(self.obj_with_texure), local_obj_with_texure)
        s3.cp(sc(self.obj_with_texure_mtl), local_obj_with_texure_mtl)
        s3.cp(sc(self.obj_with_texure_tex), local_obj_with_texure_tex)

        m = obj.load(local_obj_with_texure)

        mock_s3_open.assert_has_calls([
            mock.call(local_obj_with_texure, 'rb'),
            mock.call(local_obj_with_texure_mtl, 'r'),
        ])
        self.assertEqual(m.materials_filepath, local_obj_with_texure_mtl)
        self.assertEqual(m.texture_filepath, local_obj_with_texure_tex)
示例#9
0
    def test_loading_vertex_colors(self):
        # Mesh without vertex colors should not have vertex colors
        mesh_without_vertex_colors = obj.load(sc(self.test_obj_url))
        self.assertIsNone(mesh_without_vertex_colors.vc)

        # Mesh with vertex colors should have vertex colors
        mesh_with_vertex_colors = obj.load(
            sc(self.test_obj_with_vertex_colors_url))
        self.assertIsNotNone(mesh_with_vertex_colors.vc)

        # Check sizes
        vc_length, vc_size = mesh_with_vertex_colors.vc.shape
        v_length, _ = mesh_with_vertex_colors.v.shape
        self.assertEqual(vc_length, v_length)
        self.assertEqual(vc_size, 3)

        # Vertices should be the same
        self.assertTrue(
            (mesh_without_vertex_colors.v == mesh_with_vertex_colors.v).all())
示例#10
0
 def setUp(self):
     skip_on_import_error('lace-search')
     self.scan_fname = sc(
         's3://bodylabs-korper-assets/is/ps/shared/data/body/caesar/RawScans/csr0001a.ply'
     )
     self.scan_lmrk = sc(
         's3://bodylabs-korper-assets/is/ps/shared/data/body/caesar/Landmarks/csr0001a.lmrk'
     )
     self.template_fname = sc(
         's3://bodylabs-korper-assets/is/ps/shared/data/body/template/textured_mean_scape_female.obj'
     )
     self.template_pp = sc(
         's3://bodylabs-korper-assets/is/ps/shared/data/body/template/template_caesar_picked_points.pp'
     )
     self.scan = Mesh(filename=self.scan_fname, lmrkfilename=self.scan_lmrk)
     self.template = Mesh(filename=self.template_fname,
                          ppfilename=self.template_pp)
     self.template_without_regressors = Mesh(filename=self.template_fname,
                                             ppfilename=self.template_pp)
     self.template_without_regressors.landm_regressors = {}
     super(TestLandmarks, self).setUp()
示例#11
0
 def test_estimate_vertex_normals(self):
     # normals of a sphere should be scaled versions of the vertices
     test_sphere_path = sc(
         's3://bodylabs-korper-assets/is/ps/shared/data/body/'
         'korper_testdata/sphere.ply'
     )
     m = Mesh(filename=test_sphere_path)
     m.v -= np.mean(m.v, axis=0)
     rad = np.linalg.norm(m.v[0])
     m.estimate_vertex_normals()
     mse = np.mean(np.sqrt(np.sum((m.vn - m.v/rad)**2, axis=1)))
     self.assertTrue(mse < 0.05)
示例#12
0
 def test_loading_brings_in_normals_and_uvs(self):
     # This file is known to have vt, vn, and faces of the form 1/2/3
     texture_template = 's3://bodylabs-korper-assets/is/ps/shared/data/body/template/texture_coordinates/textured_template_low_v2.obj'
     mesh_with_texture = obj.load(sc(texture_template))
     self.assertIsNotNone(mesh_with_texture.vt)
     self.assertIsNotNone(mesh_with_texture.ft)
     self.assertEqual(mesh_with_texture.vt.shape[1], 2)
     self.assertEqual(mesh_with_texture.vt.shape[0],
                      np.max(mesh_with_texture.ft) + 1)
     self.assertIsNotNone(mesh_with_texture.vn)
     self.assertIsNotNone(mesh_with_texture.fn)
     self.assertEqual(mesh_with_texture.vn.shape[1], 3)
     self.assertEqual(mesh_with_texture.vn.shape[0],
                      np.max(mesh_with_texture.fn) + 1)
示例#13
0
    def test_cut_across_axis_by_percentile(self):
        original_mesh = Mesh(filename=sc(
            's3://bodylabs-assets/example_meshes/average_female.obj'))

        # Set up
        mesh = original_mesh.copy()
        # Sanity check
        np.testing.assert_almost_equal(mesh.v[:, 0].min(), -0.3668)
        np.testing.assert_almost_equal(mesh.v[:, 0].max(), 0.673871)
        # Act
        mesh.cut_across_axis_by_percentile(0, 25, 40)
        # Test
        np.testing.assert_almost_equal(mesh.v[:, 0].min(), 0.03, decimal=1)
        np.testing.assert_almost_equal(mesh.v[:, 0].max(), 0.10, decimal=1)
        # Visualize
        if self.debug:
            mesh.show()
示例#14
0
    def test_reading_obj_with_mtl_from_absolute_path(self, mock_s3_open):
        # This is generally a very bad idea; it makes it hard to move an obj around
        skip_if_unavailable('s3')
        obj_path = os.path.join(self.scratch_dir, 'abs_path_to_mtl.obj')
        mlt_path = os.path.join(self.scratch_dir, 'abs_path_to_mtl.mlt')
        tex_path = os.path.abspath(sc(self.obj_with_texure_tex))

        with open(obj_path, 'w') as f:
            f.write('mtllib {}\n'.format(mlt_path))
        with open(mlt_path, 'w') as f:
            f.write('map_Ka {}\n'.format(tex_path))

        m = obj.load(obj_path)

        mock_s3_open.assert_has_calls([
            mock.call(obj_path, 'rb'),
            mock.call(mlt_path, 'r'),
        ])
        self.assertEqual(m.materials_filepath, mlt_path)
        self.assertEqual(m.texture_filepath, tex_path)
示例#15
0
    def path_relative_to_mesh(filename):
        # The OBJ file we're loading may have come from a local path, an s3 url,
        # or a file cached by sc. Since OBJ defines materials and texture files
        # with paths relative to the OBJ itself, we need to cope with the various
        # possibilities and if it's a cached file make sure that the material and
        # texture have been downloaded as well.
        #
        # If an absolute path is given and the file is missing, try looking in the same directory;
        # this lets you find the most common intention when an abs path is used.
        #
        # NB: We do not support loading material & texture info from objs read
        # from filelike objects without a location on the filesystem; what would
        # the relative file names mean in that case, anyway? (unless we're given
        # a valid absolute path, in which case go for it)
        import os
        import re

        # The second term here let's us detect windows absolute paths when we're running on posix
        if filename == os.path.abspath(filename) or re.match(
                r'^.\:(\\|/)', filename):
            if s3.exists(filename):
                return filename
            else:
                filename = s3.path.basename(filename)

        if hasattr(fd, 'remotename'):
            mesh_path = fd.remotename
        elif hasattr(fd, 'name'):
            mesh_path = fd.name
        else:
            return None

        path = s3.path.join(s3.path.dirname(mesh_path), filename)
        if sc.is_cachefile(mesh_path):
            try:
                return sc(path)
            except s3.KeyNotFound:
                return None
        return path
示例#16
0
 def setUp(self):
     import tempfile
     self.tmp_dir = tempfile.mkdtemp('bodylabs-test')
     self.truth = {
         'box_v':
         np.array([[0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, -0.5],
                   [0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5],
                   [0.5, 0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5]]).T,
         'box_f':
         np.array([[0, 1, 2], [3, 2, 1], [0, 2, 4], [6, 4, 2], [0, 4, 1],
                   [5, 1, 4], [7, 5, 6], [4, 6, 5], [7, 6, 3], [2, 3, 6],
                   [7, 3, 5], [1, 5, 3]]),
         'box_fn':
         np.array([[0, 0, 1], [0, 0, 1], [1, 0, 0], [1, 0, 0], [0, 1, 0],
                   [0, 1, 0], [0, 0, -1], [-0, -0, -1], [0, -1, 0],
                   [-0, -1, -0], [-1, 0, 0], [-1, -0, -0]]),
     }
     # Because STL gives duplicated verts
     self.truth['box_v'] = self.truth['box_v'][
         self.truth['box_f'].flatten()]
     self.truth['box_f'] = np.array(range(
         self.truth['box_v'].shape[0])).reshape((-1, 3))
     self.test_stl_url = "s3://bodylabs-korper-assets/is/ps/shared/data/body/korper_testdata/test_box.stl"
     self.test_stl_path = sc(self.test_stl_url)
示例#17
0
 def test_loads_unsupported_format_raise_exception(self):
     with self.assertRaises(wrl.ParseError):
         with open(sc(self.test_obj_url)) as f:
             wrl.load(f)