Пример #1
0
    def __init__(
        self,
        vertices,
        faces,
        euler_init,
        translation_init,
        cregu=2000,
        inertia=0.96,
        damping=0.05,
    ):
        self.cregu = cregu
        self.inertia = inertia
        self.damping = damping
        self.step_factor_vertices = 0.0005
        self.step_max_vertices = 0.5
        self.step_factor_quaternion = 0.00006
        self.step_max_quaternion = 0.1
        self.step_factor_translation = 0.00005
        self.step_max_translation = 0.1

        self.mesh = TriMesh(
            faces.copy()
        )  # we do a copy to avoid negative stride not support by pytorch
        objectCenter = vertices.mean(axis=0)+translation_init
        objectRadius = np.max(np.std(vertices, axis=0))
        self.cameraCenter = objectCenter + np.array([-0.5, 0, 5]) * objectRadius

        self.scene = Scene3DPytorch()
        self.scene.setMesh(self.mesh)
        self.rigidEnergy = LaplacianRigidEnergy(self.mesh, vertices, cregu)
        self.vertices_init = torch.tensor(copy.copy(vertices))
        self.Hfactorized = None
        self.Hpreconditioner = None
        self.setMeshTransformInit(euler=euler_init, translation=translation_init)
        self.reset()
Пример #2
0
    def __init__(
        self,
        vertices,
        faces,
        euler_init,
        translation_init,
        defaultColor,
        defaultLight,
        cregu=2000,
        inertia=0.96,
        damping=0.05,
        updateLights=True,
        updateColor=True,
    ):
        self.cregu = cregu

        self.inertia = inertia
        self.damping = damping
        self.step_factor_vertices = 0.0005
        self.step_max_vertices = 0.5
        self.step_factor_quaternion = 0.00006
        self.step_max_quaternion = 0.05
        self.step_factor_translation = 0.00005
        self.step_max_translation = 0.1

        self.defaultColor = defaultColor
        self.defaultLight = defaultLight
        self.updateLights = updateLights
        self.updateColor = updateColor
        self.mesh = TriMesh(faces[:, ::-1].copy())
        objectCenter = vertices.mean(axis=0)
        objectRadius = np.max(np.std(vertices, axis=0))
        self.cameraCenter = objectCenter + np.array([0, 0, 9]) * objectRadius

        self.scene = Scene3D()
        self.scene.setMesh(self.mesh)
        self.rigidEnergy = LaplacianRigidEnergy(self.mesh, vertices, cregu)
        self.vertices_init = copy.copy(vertices)
        self.Hfactorized = None
        self.Hpreconditioner = None
        self.setMeshTransformInit(euler=euler_init,
                                  translation=translation_init)
        self.reset()
Пример #3
0
class MeshRGBFitterWithPose:
    def __init__(
        self,
        vertices,
        faces,
        euler_init,
        translation_init,
        defaultColor,
        defaultLight,
        cregu=2000,
        inertia=0.96,
        damping=0.05,
        updateLights=True,
        updateColor=True,
    ):
        self.cregu = cregu

        self.inertia = inertia
        self.damping = damping
        self.step_factor_vertices = 0.0005
        self.step_max_vertices = 0.5
        self.step_factor_quaternion = 0.00006
        self.step_max_quaternion = 0.05
        self.step_factor_translation = 0.00005
        self.step_max_translation = 0.1

        self.defaultColor = defaultColor
        self.defaultLight = defaultLight
        self.updateLights = updateLights
        self.updateColor = updateColor
        self.mesh = TriMesh(faces[:, ::-1].copy())
        objectCenter = vertices.mean(axis=0)
        objectRadius = np.max(np.std(vertices, axis=0))
        self.cameraCenter = objectCenter + np.array([0, 0, 9]) * objectRadius

        self.scene = Scene3D()
        self.scene.setMesh(self.mesh)
        self.rigidEnergy = LaplacianRigidEnergy(self.mesh, vertices, cregu)
        self.vertices_init = copy.copy(vertices)
        self.Hfactorized = None
        self.Hpreconditioner = None
        self.setMeshTransformInit(euler=euler_init,
                                  translation=translation_init)
        self.reset()

    def setBackgroundColor(self, backgroundColor):
        self.scene.setBackground(
            np.tile(backgroundColor[None, None, :],
                    (self.SizeH, self.SizeW, 1)))

    def setMeshTransformInit(self, euler, translation):
        self.transformQuaternionInit = scipy.spatial.transform.Rotation.from_euler(
            "zyx", euler).as_quat()
        self.transformTranslationInit = translation

    def reset(self):
        self.vertices = copy.copy(self.vertices_init)
        self.speed_vertices = np.zeros(self.vertices.shape)
        self.transformQuaternion = copy.copy(self.transformQuaternionInit)
        self.transformTranslation = copy.copy(self.transformTranslationInit)
        self.speed_translation = np.zeros(3)
        self.speed_quaternion = np.zeros(4)

        self.handColor = copy.copy(self.defaultColor)
        self.ligthDirectional = copy.copy(self.defaultLight["directional"])
        self.ambiantLight = copy.copy(self.defaultLight["ambiant"])

        self.speed_ligthDirectional = np.zeros(self.ligthDirectional.shape)
        self.speed_ambiantLight = np.zeros(self.ambiantLight.shape)
        self.speed_handColor = np.zeros(self.handColor.shape)

    def setImage(self, handImage, focal=None):
        self.SizeW = handImage.shape[1]
        self.SizeH = handImage.shape[0]
        assert handImage.ndim == 3
        self.handImage = handImage
        if focal is None:
            focal = 2 * self.SizeW

        R = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]])
        T = -R.T.dot(self.cameraCenter)
        self.CameraMatrix = np.array([[focal, 0, self.SizeW / 2],
                                      [0, focal, self.SizeH / 2],
                                      [0, 0, 1]]).dot(np.column_stack((R, T)))
        self.iter = 0

    def render(self):
        q_normalized = normalize(
            self.transformQuaternion
        )  # that will lead to a gradient that is in the tangeant space
        vertices_transformed = (qrot(q_normalized, self.vertices) +
                                self.transformTranslation)
        self.mesh.setVertices(vertices_transformed)
        self.scene.setLight(ligthDirectional=self.ligthDirectional,
                            ambiantLight=self.ambiantLight)
        self.mesh.setVerticesColors(np.tile(self.handColor,
                                            (self.mesh.nbV, 1)))
        Abuffer = self.scene.render(self.CameraMatrix,
                                    resolution=(self.SizeW, self.SizeH))
        return Abuffer

    def render_backward(self, Abuffer_b):
        self.scene.clear_gradients()
        self.scene.render_backward(Abuffer_b)
        self.handColor_b = np.sum(self.mesh.verticesColors_b, axis=0)
        self.ligthDirectional_b = self.scene.lightDirectional_b
        self.ambiantLight_b = self.scene.ambiantLight_b
        vertices_transformed_b = self.scene.mesh.vertices_b
        self.transformTranslation_b = np.sum(vertices_transformed_b, axis=0)
        q_normalized = normalize(self.transformQuaternion)
        q_normalized_b, self.vertices_b = qrot_backward(
            q_normalized, self.vertices, vertices_transformed_b)
        self.transformQuaternion_b = normalize_backward(
            self.transformQuaternion, q_normalized_b
        )  # that will lead to a gradient that is in the tangeant space
        return

    def step(self):
        self.vertices = self.vertices - np.mean(self.vertices, axis=0)[None, :]

        Abuffer = self.render()

        diffImage = np.sum((Abuffer - self.handImage)**2, axis=2)
        Abuffer_b = 2 * (Abuffer - self.handImage)
        EData = np.sum(diffImage)

        E_rigid, grad_rigidity, approx_hessian_rigidity = self.rigidEnergy.eval(
            self.vertices)
        Energy = EData + E_rigid
        print("Energy=%f : EData=%f E_rigid=%f" % (Energy, EData, E_rigid))

        self.render_backward(Abuffer_b)

        self.vertices_b = self.vertices_b - np.mean(self.vertices_b,
                                                    axis=0)[None, :]
        # update v
        G = self.vertices_b + grad_rigidity

        def mult_and_clamp(x, a, t):
            return np.minimum(np.maximum(x * a, -t), t)

        inertia = self.inertia

        # update vertices
        step_vertices = mult_and_clamp(-G, self.step_factor_vertices,
                                       self.step_max_vertices)
        self.speed_vertices = (1 -
                               self.damping) * (self.speed_vertices * inertia +
                                                (1 - inertia) * step_vertices)
        self.vertices = self.vertices + self.speed_vertices
        # update rotation
        step_quaternion = mult_and_clamp(
            -self.transformQuaternion_b,
            self.step_factor_quaternion,
            self.step_max_quaternion,
        )
        self.speed_quaternion = (1 - self.damping) * (
            self.speed_quaternion * inertia + (1 - inertia) * step_quaternion)
        self.transformQuaternion = self.transformQuaternion + self.speed_quaternion
        self.transformQuaternion = self.transformQuaternion / np.linalg.norm(
            self.transformQuaternion)
        # update translation
        step_translation = mult_and_clamp(
            -self.transformTranslation_b,
            self.step_factor_translation,
            self.step_max_translation,
        )
        self.speed_translation = (
            1 - self.damping) * (self.speed_translation * inertia +
                                 (1 - inertia) * step_translation)
        self.transformTranslation = self.transformTranslation + self.speed_translation
        # update directional light
        step = -self.ligthDirectional_b * 0.0001
        self.speed_ligthDirectional = (1 - self.damping) * (
            self.speed_ligthDirectional * inertia + (1 - inertia) * step)
        self.ligthDirectional = self.ligthDirectional + self.speed_ligthDirectional
        # update ambiant light
        step = -self.ambiantLight_b * 0.0001
        self.speed_ambiantLight = (1 - self.damping) * (
            self.speed_ambiantLight * inertia + (1 - inertia) * step)
        self.ambiantLight = self.ambiantLight + self.speed_ambiantLight
        # update hand color
        step = -self.handColor_b * 0.00001
        self.speed_handColor = (1 - self.damping) * (
            self.speed_handColor * inertia + (1 - inertia) * step)
        self.handColor = self.handColor + self.speed_handColor

        self.iter += 1
        return Energy, Abuffer, diffImage
Пример #4
0
class MeshDepthFitter:
    def __init__(
        self,
        vertices,
        faces,
        euler_init,
        translation_init,
        cregu=2000,
        inertia=0.96,
        damping=0.05,
    ):
        self.cregu = cregu
        self.inertia = inertia
        self.damping = damping
        self.step_factor_vertices = 0.0005
        self.step_max_vertices = 0.5
        self.step_factor_quaternion = 0.00006
        self.step_max_quaternion = 0.1
        self.step_factor_translation = 0.00005
        self.step_max_translation = 0.1

        self.mesh = TriMesh(faces[:, ::-1].copy(
        ))  # we do a copy to avoid negative stride not support by pytorch
        objectCenter = vertices.mean(axis=0)
        objectRadius = np.max(np.std(vertices, axis=0))
        self.cameraCenter = objectCenter + np.array([-0.5, 0, 5
                                                     ]) * objectRadius

        self.scene = Scene3D()
        self.scene.setMesh(self.mesh)
        self.rigidEnergy = LaplacianRigidEnergy(self.mesh, vertices, cregu)
        self.vertices_init = copy.copy(vertices)
        self.Hfactorized = None
        self.Hpreconditioner = None
        self.setMeshTransformInit(euler=euler_init,
                                  translation=translation_init)
        self.reset()

    def setMeshTransformInit(self, euler, translation):
        self.transformQuaternionInit = scipy.spatial.transform.Rotation.from_euler(
            "zyx", euler).as_quat()
        self.transformTranslationInit = translation

    def reset(self):
        self.vertices = copy.copy(self.vertices_init)
        self.speed_vertices = np.zeros(self.vertices_init.shape)
        self.transformQuaternion = copy.copy(self.transformQuaternionInit)
        self.transformTranslation = copy.copy(self.transformTranslationInit)
        self.speed_translation = np.zeros(3)
        self.speed_quaternion = np.zeros(4)

    def setMaxDepth(self, maxDepth):
        self.scene.maxDepth = maxDepth
        self.scene.setBackground(
            np.full((self.SizeH, self.SizeW, 1), maxDepth, dtype=np.float))

    def setDepthScale(self, depthScale):
        self.depthScale = depthScale

    def setImage(self, handImage, focal=None):
        self.SizeW = handImage.shape[1]
        self.SizeH = handImage.shape[0]
        assert handImage.ndim == 2
        self.handImage = handImage
        if focal is None:
            focal = 2 * self.SizeW

        R = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]])
        T = -R.T.dot(self.cameraCenter)
        self.CameraMatrix = np.array([[focal, 0, self.SizeW / 2],
                                      [0, focal, self.SizeH / 2],
                                      [0, 0, 1]]).dot(np.column_stack((R, T)))
        self.iter = 0

    def render(self):
        q_normalized = normalize(
            self.transformQuaternion
        )  # that will lead to a gradient that is in the tangeant space
        vertices_transformed = (qrot(q_normalized, self.vertices) +
                                self.transformTranslation)
        self.mesh.setVertices(vertices_transformed)
        self.DepthNotCliped = self.scene.renderDepth(
            self.CameraMatrix,
            resolution=(self.SizeW, self.SizeH),
            depth_scale=self.depthScale,
        )
        Depth = np.clip(self.DepthNotCliped, 0, self.scene.maxDepth)
        return Depth

    def render_backward(self, Depth_b):
        self.scene.clear_gradients()
        Depth_b[self.DepthNotCliped < 0] = 0
        Depth_b[self.DepthNotCliped > self.scene.maxDepth] = 0
        self.scene.renderDepth_backward(Depth_b)
        vertices_transformed_b = self.scene.mesh.vertices_b
        self.transformTranslation_b = np.sum(vertices_transformed_b, axis=0)
        q_normalized = normalize(self.transformQuaternion)
        q_normalized_b, self.vertices_b = qrot_backward(
            q_normalized, self.vertices, vertices_transformed_b)
        self.transformQuaternion_b = normalize_backward(
            self.transformQuaternion, q_normalized_b
        )  # that will lead to a gradient that is in the tangeant space
        return

    def step(self):

        self.vertices = self.vertices - np.mean(self.vertices, axis=0)[None, :]
        Depth = self.render()

        diffImage = np.sum((Depth - self.handImage[:, :, None])**2, axis=2)
        EData = np.sum(diffImage)
        Depth_b = 2 * (Depth - self.handImage[:, :, None])
        self.render_backward(Depth_b)

        self.vertices_b = self.vertices_b - np.mean(self.vertices_b,
                                                    axis=0)[None, :]
        GradData = self.vertices_b
        # update v

        E_rigid, grad_rigidity, approx_hessian_rigidity = self.rigidEnergy.eval(
            self.vertices)
        Energy = EData + E_rigid
        print("Energy=%f : EData=%f E_rigid=%f" % (Energy, EData, E_rigid))

        # update v
        G = GradData + grad_rigidity

        def mult_and_clamp(x, a, t):
            return np.minimum(np.maximum(x * a, -t), t)

        inertia = self.inertia
        # update vertices
        step_vertices = mult_and_clamp(-G, self.step_factor_vertices,
                                       self.step_max_vertices)
        self.speed_vertices = (
            1 - self.damping) * (self.speed_vertices * self.inertia +
                                 (1 - self.inertia) * step_vertices)
        self.vertices = self.vertices + self.speed_vertices
        # update rotation
        step_quaternion = mult_and_clamp(
            -self.transformQuaternion_b,
            self.step_factor_quaternion,
            self.step_max_quaternion,
        )
        self.speed_quaternion = (1 - self.damping) * (
            self.speed_quaternion * inertia + (1 - inertia) * step_quaternion)
        self.transformQuaternion = self.transformQuaternion + self.speed_quaternion
        self.transformQuaternion = self.transformQuaternion / np.linalg.norm(
            self.transformQuaternion)
        # update translation
        step_translation = mult_and_clamp(
            -self.transformTranslation_b,
            self.step_factor_translation,
            self.step_max_translation,
        )
        self.speed_translation = (
            1 - self.damping) * (self.speed_translation * inertia +
                                 (1 - inertia) * step_translation)
        self.transformTranslation = self.transformTranslation + self.speed_translation

        self.iter += 1
        return Energy, Depth[:, :, 0], diffImage
Пример #5
0
class MeshDepthFitter:
    def __init__(
        self,
        vertices,
        faces,
        euler_init,
        translation_init,
        cregu=2000,
        inertia=0.96,
        damping=0.05,
    ):
        self.cregu = cregu
        self.inertia = inertia
        self.damping = damping
        self.step_factor_vertices = 0.0005
        self.step_max_vertices = 0.5
        self.step_factor_quaternion = 0.00006
        self.step_max_quaternion = 0.1
        self.step_factor_translation = 0.00005
        self.step_max_translation = 0.1

        self.mesh = TriMesh(
            faces.copy()
        )  # we do a copy to avoid negative stride not support by pytorch
        objectCenter = vertices.mean(axis=0)+translation_init
        objectRadius = np.max(np.std(vertices, axis=0))
        self.cameraCenter = objectCenter + np.array([-0.5, 0, 5]) * objectRadius

        self.scene = Scene3DPytorch()
        self.scene.setMesh(self.mesh)
        self.rigidEnergy = LaplacianRigidEnergy(self.mesh, vertices, cregu)
        self.vertices_init = torch.tensor(copy.copy(vertices))
        self.Hfactorized = None
        self.Hpreconditioner = None
        self.setMeshTransformInit(euler=euler_init, translation=translation_init)
        self.reset()

    def setMeshTransformInit(self, euler, translation):
        self.transformQuaternionInit = scipy.spatial.transform.Rotation.from_euler(
            "zyx", euler
        ).as_quat()
        self.transformTranslationInit = translation

    def reset(self):
        self.vertices = copy.copy(self.vertices_init)
        self.speed_vertices = np.zeros(self.vertices_init.shape)
        self.transformQuaternion = copy.copy(self.transformQuaternionInit)
        self.transformTranslation = copy.copy(self.transformTranslationInit)
        self.speed_translation = np.zeros(3)
        self.speed_quaternion = np.zeros(4)

    def setMaxDepth(self, maxDepth):
        self.scene.maxDepth = maxDepth
        self.scene.setBackground(
            np.full((self.SizeH, self.SizeW, 1), maxDepth, dtype=np.float)
        )

    def setDepthScale(self, depthScale):
        self.depthScale = depthScale

    def setImage(self, handImage, focal=None):
        self.SizeW = handImage.shape[1]
        self.SizeH = handImage.shape[0]
        assert handImage.ndim == 2
        self.handImage = handImage
        if focal is None:
            focal = 2 * self.SizeW

        R = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]])
        T = -R.T.dot(self.cameraCenter)
        self.CameraMatrix = np.array(
            [[focal, 0, self.SizeW / 2], [0, focal, self.SizeH / 2], [0, 0, 1]]
        ).dot(np.column_stack((R, T)))
        self.iter = 0

    def step(self):
        self.vertices = self.vertices - torch.mean(self.vertices, dim=0)[None, :]
        # vertices_with_grad = self.vertices.clone().requires_grad(True)
        vertices_with_grad = self.vertices.clone().detach().requires_grad_(True)
        vertices_with_grad_centered = (
            vertices_with_grad - torch.mean(vertices_with_grad, dim=0)[None, :]
        )
        quaternion_with_grad = torch.tensor(
            self.transformQuaternion, dtype=torch.float64, requires_grad=True
        )
        translation_with_grad = torch.tensor(
            self.transformTranslation, dtype=torch.float64, requires_grad=True
        )

        q_normalized = (
            quaternion_with_grad / quaternion_with_grad.norm()
        )  # that will lead to a gradient that is in the tangeant space
        vertices_with_grad_transformed = (
            qrot(q_normalized, vertices_with_grad_centered) + translation_with_grad
        )

        self.mesh.setVertices(vertices_with_grad_transformed)

        depth_scale = 1 * self.depthScale
        Depth = self.scene.renderDepth(
            self.CameraMatrix,
            resolution=(self.SizeW, self.SizeH),
            depth_scale=depth_scale,
        )
        Depth = torch.clamp(Depth, 0, self.scene.maxDepth)

        diffImage = torch.sum(
            (Depth - torch.tensor(self.handImage[:, :, None])) ** 2, dim=2
        )
        loss = torch.sum(diffImage)

        loss.backward()
        EData = loss.detach().numpy()

        GradData = vertices_with_grad.grad.numpy()

        E_rigid, grad_rigidity, approx_hessian_rigidity = self.rigidEnergy.eval(
            self.vertices.numpy()
        )
        Energy = EData + E_rigid
        print("Energy=%f : EData=%f E_rigid=%f" % (Energy, EData, E_rigid))

        # update v
        G = GradData + grad_rigidity

        def mult_and_clamp(x, a, t):
            return np.minimum(np.maximum(x * a, -t), t)

        # update vertices
        step_vertices = mult_and_clamp(
            -G, self.step_factor_vertices, self.step_max_vertices
        )
        self.speed_vertices = (1 - self.damping) * (
            self.speed_vertices * self.inertia + (1 - self.inertia) * step_vertices
        )
        self.vertices = self.vertices + torch.tensor(self.speed_vertices)
        # update rotation
        step_quaternion = mult_and_clamp(
            -quaternion_with_grad.grad.numpy(),
            self.step_factor_quaternion,
            self.step_max_quaternion,
        )
        self.speed_quaternion = (1 - self.damping) * (
            self.speed_quaternion * self.inertia + (1 - self.inertia) * step_quaternion
        )
        self.transformQuaternion = self.transformQuaternion + self.speed_quaternion
        self.transformQuaternion = self.transformQuaternion / np.linalg.norm(
            self.transformQuaternion
        )
        # update translation

        step_translation = mult_and_clamp(
            -translation_with_grad.grad.numpy(),
            self.step_factor_translation,
            self.step_max_translation,
        )
        self.speed_translation = (1 - self.damping) * (
            self.speed_translation * self.inertia
            + (1 - self.inertia) * step_translation
        )
        self.transformTranslation = self.transformTranslation + self.speed_translation

        self.iter += 1
        return Energy, Depth[:, :, 0].detach().numpy(), diffImage.detach().numpy()