mambazjp's picture
Upload 82 files
8870024
raw
history blame
2.84 kB
"""
Copyright 2016 Max Planck Society, Matthew Loper. All rights reserved.
This software is provided for research purposes only.
By using this software you agree to the terms of the SMPLify license here:
http://smplify.is.tue.mpg.de/license
This script implements the Geman-McClure robustifier as chumpy object.
"""
#!/usr/bin/env python
import numpy as np
import scipy
import scipy.sparse as sp
from chumpy import Ch
__all__ = ['GMOf']
def GMOf(x, sigma):
"""Given x and sigma in some units (say mm),
returns robustified values (in same units),
by making use of the Geman-McClure robustifier."""
result = SignedSqrt(x=GMOfInternal(x=x, sigma=sigma))
return result
class SignedSqrt(Ch):
dterms = ('x', )
terms = ()
def compute_r(self):
return np.sqrt(np.abs(self.x.r)) * np.sign(self.x.r)
def compute_dr_wrt(self, wrt):
if wrt is self.x:
result = (.5 / np.sqrt(np.abs(self.x.r)))
result = np.nan_to_num(result)
result *= (self.x.r != 0).astype(np.uint32)
return sp.spdiags(result.ravel(), [0], self.x.r.size,
self.x.r.size)
class GMOfInternal(Ch):
dterms = 'x', 'sigma'
def on_changed(self, which):
if 'sigma' in which:
assert (self.sigma.r > 0)
if 'x' in which:
self.squared_input = self.x.r**2.
def compute_r(self):
return (self.sigma.r**2 *
(self.squared_input /
(self.sigma.r**2 + self.squared_input))) * np.sign(self.x.r)
def compute_dr_wrt(self, wrt):
if wrt is not self.x and wrt is not self.sigma:
return None
squared_input = self.squared_input
result = []
if wrt is self.x:
dx = self.sigma.r**2 / (self.sigma.r**2 + squared_input
) - self.sigma.r**2 * (squared_input / (
self.sigma.r**2 + squared_input)**2)
dx = 2 * self.x.r * dx
result.append(
scipy.sparse.spdiags(
(dx * np.sign(self.x.r)).ravel(), [0],
self.x.r.size,
self.x.r.size,
format='csc'))
if wrt is self.sigma:
ds = 2 * self.sigma.r * (squared_input / (
self.sigma.r**2 + squared_input)) - 2 * self.sigma.r**3 * (
squared_input / (self.sigma.r**2 + squared_input)**2)
result.append(
scipy.sparse.spdiags(
(ds * np.sign(self.x.r)).ravel(), [0],
self.x.r.size,
self.x.r.size,
format='csc'))
if len(result) == 1:
return result[0]
else:
return np.sum(result).tocsc()