2013-12-12 25 views
5

Tôi có cùng một vấn đề như được mô tả ở đây: how to perform coordinates affine transformation using python?làm thế nào để thực hiện tọa độ affine chuyển đổi bằng cách sử dụng python? phần 2

Tôi đã cố gắng sử dụng phương pháp được mô tả nhưng một số lý do tôi sẽ nhận được thông báo lỗi. Thay đổi tôi đã thực hiện cho mã là thay thế các điểm hệ thống chính và hệ thống phụ. Tôi tạo ra các điểm phối hợp thứ cấp bằng cách sử dụng origo khác nhau. Trong trường hợp thực tế mà tôi đang nghiên cứu chủ đề này sẽ có một số lỗi khi đo tọa độ.

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) 

Lỗi tôi nhận được từ khi thực hiện được sau.

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

Điều gì có thể là vấn đề?

Trả lời

15

Vấn đề là ma trận của bạn là số ít, có nghĩa là nó không thể đảo ngược. Vì bạn đang cố gắng để đảo ngược nó, đó là một vấn đề. Chủ đề mà bạn liên kết đến là một giải pháp cơ bản cho vấn đề của bạn, nhưng nó không thực sự là giải pháp tốt nhất. Thay vì chỉ đảo ngược ma trận, những gì bạn thực sự muốn làm là giải quyết vấn đề giảm thiểu ô vuông nhỏ nhất để tìm ma trận biến đổi affine tối ưu cho dữ liệu có thể nhiễu của bạn. Đây là cách bạn sẽ làm điều đó:

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

Lý do mà ma trận ban đầu của bạn là số ít là phối hợp thứ ba của bạn luôn luôn là zero, vì vậy không có cách nào để nói những gì biến đổi trên mà phối hợp nên (zero lần bất cứ điều gì cho không, vì vậy bất kỳ giá trị nào cũng hoạt động).

In giá trị của A cho bạn biết sự biến đổi mà bình phương nhỏ nhất đã được tìm thấy:

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

kết quả trong

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

tương đương với x2 = -x1 + 650, y2 = y1 - 600, z2 = 0 nơi x1, y1, z1 là tọa độ trong hệ thống ban đầu của bạn và x2, y2, z2 là các tọa độ trong hệ thống mới của bạn. Như bạn có thể thấy, các ô nhỏ nhất chỉ cần đặt tất cả các cụm từ có liên quan đến thứ nguyên thứ ba thành 0, vì hệ thống của bạn thực sự là hai chiều.

Các vấn đề liên quan