2013-12-12 31 views
5

Ho lo stesso problema, come descritto di seguito: how to perform coordinates affine transformation using python?come eseguire le coordinate di trasformazione affine usando python? parte 2

Stavo cercando di utilizzare il metodo descritto, ma qualche ragione mi metterò i messaggi di errore. Le modifiche apportate al codice erano la sostituzione del sistema primario e dei punti del sistema secondario. Ho creato punti di coordinate secondarie utilizzando origini diverse. Nel caso reale per il quale sto studiando questo argomento avrà degli errori nel misurare le coordinate.

primary_system1 = (40.0, 1160.0, 0.0) 
primary_system2 = (40.0, 40.0, 0.0) 
primary_system3 = (260.0, 40.0, 0.0) 
primary_system4 = (260.0, 1160.0, 0.0) 

secondary_system1 = (610.0, 560.0, 0.0) 
secondary_system2 = (610.0,-560.0, 0.0) 
secondary_system3 = (390.0, -560.0, 0.0) 
secondary_system4 = (390.0, 560.0, 0.0) 

errore che ricevo da quando si eseguono seguendo.

*Traceback (most recent call last): 
    File "affine_try.py", line 57, in <module> 
    secondary_system3, secondary_system4) 
    File "affine_try.py", line 22, in solve_affine 
    A2 = y * x.I 
    File "/usr/lib/python2.7/dist-packages/numpy/matrixlib/defmatrix.py", line 850, in getI 
    return asmatrix(func(self)) 
    File "/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py", line 445, in inv 
    return wrap(solve(a, identity(a.shape[0], dtype=a.dtype))) 
    File "/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py", line 328, in solve 
    raise LinAlgError, 'Singular matrix' 
numpy.linalg.linalg.LinAlgError: Singular matrix* 

Quale potrebbe essere il problema?

risposta

15

Il problema è che la matrice è singolare, il che significa che non è invertibile. Dal momento che stai cercando di prenderne l'inverso, questo è un problema. Il thread a cui sei collegato è una soluzione di base al tuo problema, ma non è davvero la soluzione migliore. Piuttosto che semplicemente invertendo la matrice, ciò che realmente si vuole fare è risolvere un problema di minimizzazione dei minimi quadrati per trovare la matrice di trasformazione affine ottimale per i dati potenzialmente rumorosi. Ecco come l'hai fatto:

import numpy as np 

primary = np.array([[40., 1160., 0.], 
        [40., 40., 0.], 
        [260., 40., 0.], 
        [260., 1160., 0.]]) 

secondary = np.array([[610., 560., 0.], 
         [610., -560., 0.], 
         [390., -560., 0.], 
         [390., 560., 0.]]) 

# Pad the data with ones, so that our transformation can do translations too 
n = primary.shape[0] 
pad = lambda x: np.hstack([x, np.ones((x.shape[0], 1))]) 
unpad = lambda x: x[:,:-1] 
X = pad(primary) 
Y = pad(secondary) 

# Solve the least squares problem X * A = Y 
# to find our transformation matrix A 
A, res, rank, s = np.linalg.lstsq(X, Y) 

transform = lambda x: unpad(np.dot(pad(x), A)) 

print "Target:" 
print secondary 
print "Result:" 
print transform(primary) 
print "Max error:", np.abs(secondary - transform(primary)).max() 

La ragione per cui la vostra matrice originale era singolare è che la vostra terza coordinata è sempre zero, quindi non c'è modo di dire quello che la trasformazione su che coordinano dovrebbe essere (zero volte nulla dà zero, quindi qualsiasi valore funzionerebbe).

Stampa del valore della A ti dice la trasformazione che dei minimi quadrati ha trovato:

A[np.abs(A) < 1e-10] = 0 # set really small values to zero 
print A 

risultati in

[[ -1. 0. 0. 0.] 
[ 0. 1. 0. 0.] 
[ 0. 0. 0. 0.] 
[ 650. -600. 0. 1.]] 

che equivale a x2 = -x1 + 650, y2 = y1 - 600, z2 = 0 dove x1, y1, z1 sono le coordinate nel sistema originale e x2, y2, z2 sono le coordinate nel nuovo sistema. Come puoi vedere, i minimi quadrati impostano a zero tutti i termini relativi alla terza dimensione, poiché il tuo sistema è realmente bidimensionale.