Skip to content

Commit

Permalink
Fix affines.decompose44() behavior in presence of NANs
Browse files Browse the repository at this point in the history
  • Loading branch information
EliaCereda committed Feb 21, 2024
1 parent 3cfd248 commit f573df6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 18 deletions.
30 changes: 12 additions & 18 deletions transforms3d/affines.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np

from .shears import striu2mat
from .utils import diag_2d, transpose_2d, unpack
from .utils import diag_2d, transpose_2d, unpack, vdot_batch


def decompose44(A44):
Expand Down Expand Up @@ -49,26 +49,20 @@ def decompose44(A44):
Examples
--------
>>> T = [20, 30, 40] # translations
>>> R = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] # rotation matrix
>>> Z = [2.0, 3.0, 4.0] # zooms
>>> S = [0.2, 0.1, 0.3] # shears
>>> T = [[20, 30, 40], [50, 60, 70]]
>>> R = [[[0, -1, 0], [1, 0, 0], [0, 0, 1]], [[1, 0, 0], [0, 0, -1], [0, 1, 0]]]
>>> Z = [[2.0, 3.0, 4.0], [-1.0, 2.0, 4.0]]
>>> S = None # FIXME: Not implemented [[0.2, 0.1, 0.3], [0.4, 0.5, 0.6]]
>>> # Now we make an affine matrix
>>> A = np.eye(4)
>>> Smat = np.array([[1, S[0], S[1]],
... [0, 1, S[2]],
... [0, 0, 1]])
>>> RZS = np.dot(R, np.dot(np.diag(Z), Smat))
>>> A[:3,:3] = RZS
>>> A[:-1,-1] = T # set translations
>>> A = compose(T, R, Z, S)
>>> Tdash, Rdash, Zdash, Sdash = decompose44(A)
>>> np.allclose(T, Tdash)
True
>>> np.allclose(R, Rdash)
True
>>> np.allclose(Z, Zdash)
True
>>> np.allclose(S, Sdash)
>>> # FIXME: Not implemented np.allclose(S, Sdash)
True
Notes
Expand Down Expand Up @@ -134,18 +128,18 @@ def decompose44(A44):
M0 /= sx[..., np.newaxis]

# orthogonalize M1 with respect to M0
sx_sxy = np.vdot(M0, M1)
M1 -= sx_sxy * M0
sx_sxy = vdot_batch(M0, M1)
M1 -= sx_sxy[..., np.newaxis] * M0

# extract y scale and normalize
sy = np.sqrt(np.sum(M1**2, axis=-1))
M1 /= sy[..., np.newaxis]
sxy = sx_sxy / sx

# orthogonalize M2 with respect to M0 and M1
sx_sxz = np.vdot(M0, M2)
sy_syz = np.vdot(M1, M2)
M2 -= (sx_sxz * M0 + sy_syz * M1)
sx_sxz = vdot_batch(M0, M2)
sy_syz = vdot_batch(M1, M2)
M2 -= (sx_sxz[..., np.newaxis] * M0 + sy_syz[..., np.newaxis] * M1)

# extract z scale and normalize
sz = np.sqrt(np.sum(M2**2, axis=-1))
Expand Down
24 changes: 24 additions & 0 deletions transforms3d/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,27 @@ def transpose_2d(array):
(128, 3, 2)
'''
return np.transpose(array, (*range(array.ndim - 2), -1, -2))

def vdot_batch(a, b):
''' Compute the vector dot product on batches of 1D arrays
Parameters
----------
a, b : array-like batches of 1D arrays with shape (..., N)
Returns
-------
out : np.ndarray with shape (...)
sum-product of the last dimension from arrays a, b
Examples
--------
>>> a = np.array([[0, 1, 2], [2, 3, 4]])
>>> b = np.array([[2, 2, 2], [3, 3, 3]])
>>> c = vdot_batch(a, b)
>>> c.shape
(2,)
>>> c
array([ 6, 27])
'''
return np.einsum('...i,...i', a, b)

0 comments on commit f573df6

Please sign in to comment.