2013-12-12 24 views
5

Mam ten sam problem, jak opisano tutaj: how to perform coordinates affine transformation using python?jak wykonać współrzędne transformacji afinicznej przy użyciu Pythona? część 2

starałem się wykorzystać metodę opisaną ale z jakiegoś powodu będę się komunikaty o błędach. Zmiany dokonane w kodzie polegały na zamianie systemu podstawowego i dodatkowych punktów systemowych. Stworzyłem drugorzędne punkty współrzędnych, używając różnych oryginałów. W prawdziwym przypadku, dla którego studiuję ten temat będzie miał błędy podczas pomiaru współrzędnych.

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) 

Błąd otrzymuję od kiedy wykonujący obserwuje.

*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* 

Jaki może być problem?

Odpowiedz

15

Problem polega na tym, że macierz jest pojedyncza, co oznacza, że ​​nie jest odwracalna. Ponieważ próbujesz przyjąć odwrotność tego, to jest problem. Wątek, z którym się łączysz jest podstawowym rozwiązaniem problemu, ale nie jest to najlepsze rozwiązanie. Zamiast odwracać matrycę, to, co tak naprawdę chcesz zrobić, to rozwiązać problem minimalizacji kwadratów najmniejszych kwadratów, aby znaleźć optymalną macierz transformacji afinicznej dla możliwie hałaśliwych danych. Oto w jaki sposób to zrobić:

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() 

Dlatego, że oryginalna matryca była pojedyncza jest to, że trzecia współrzędna jest zawsze zero, więc nie ma sposobu, aby powiedzieć, co transformacji na które koordynują powinny być (zero razy coś daje zero, więc każda wartość zadziała).

Drukowanie wartość A informuje o transformację najmniejszych kwadratów znalazła:

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

wyniki w

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

co odpowiada x2 = -x1 + 650, y2 = y1 - 600, z2 = 0 gdzie x1, y1, z1 są współrzędnymi w oryginalnym systemie i x2, y2, z2 są współrzędnymi w twoim nowym systemie. Jak widać, najmniejsze kwadraty po prostu ustawiają wszystkie pojęcia związane z trzecim wymiarem na zero, ponieważ twój system jest naprawdę dwuwymiarowy.