projection orthogonale avec numpy
J'ai une liste de 3D-points pour lesquels j'ai calculer un avion par numpy.linalg.lstsq - méthode. Mais Maintenant, je veux faire une projection orthogonale, pour chaque point, dans cet avion, mais je ne trouve pas mon erreur:
from numpy.linalg import lstsq
def VecProduct(vek1, vek2):
return (vek1[0]*vek2[0] + vek1[1]*vek2[1] + vek1[2]*vek2[2])
def CalcPlane(x, y, z):
# x, y and z are given in lists
n = len(x)
sum_x = sum_y = sum_z = sum_xx = sum_yy = sum_xy = sum_xz = sum_yz = 0
for i in range(n):
sum_x += x[i]
sum_y += y[i]
sum_z += z[i]
sum_xx += x[i]*x[i]
sum_yy += y[i]*y[i]
sum_xy += x[i]*y[i]
sum_xz += x[i]*z[i]
sum_yz += y[i]*z[i]
M = ([sum_xx, sum_xy, sum_x], [sum_xy, sum_yy, sum_y], [sum_x, sum_y, n])
b = (sum_xz, sum_yz, sum_z)
a,b,c = lstsq(M, b)[0]
'''
z = a*x + b*y + c
a*x = z - b*y - c
x = -(b/a)*y + (1/a)*z - c/a
'''
r0 = [-c/a,
0,
0]
u = [-b/a,
1,
0]
v = [1/a,
0,
1]
xn = []
yn = []
zn = []
# orthogonalize u and v with Gram-Schmidt to get u and w
uu = VecProduct(u, u)
vu = VecProduct(v, u)
fak0 = vu/uu
erg0 = [val*fak0 for val in u]
w = [v[0]-erg0[0],
v[1]-erg0[1],
v[2]-erg0[2]]
ww = VecProduct(w, w)
# P_new = ((x*u)/(u*u))*u + ((x*w)/(w*w))*w
for i in range(len(x)):
xu = VecProduct([x[i], y[i], z[i]], u)
xw = VecProduct([x[i], y[i], z[i]], w)
fak1 = xu/uu
fak2 = xw/ww
erg1 = [val*fak1 for val in u]
erg2 = [val*fak2 for val in w]
erg = [erg1[0]+erg2[0], erg1[1]+erg2[1], erg1[2]+erg2[2]]
erg[0] += r0[0]
xn.append(erg[0])
yn.append(erg[1])
zn.append(erg[2])
return (xn,yn,zn)
Cela me renvoie une liste de points qui sont tous dans un avion, mais quand je les affiche, ils ne sont pas à la position qu'ils devraient être.
Je crois qu'il existe déjà un certain nombre de méthode pour résoudre ce problème, mais je ne pouvais pas trouver tout =(
J'ai trouvé mon erreur: j'ai fait une fausse hypothèse: Mon calcul pour P_new est faux. C'est correct: P_new = r0 + (((x-r0)*u)/(uu))*u + (((x-r0)*w)/(ww))*w
OriginalL'auteur Munchkin | 2013-07-24
Vous devez vous connecter pour publier un commentaire.
Vous faites une mauvaise utilisation de
np.lstsq
, puisque vous le nourrissez un précalculées matrice de 3x3, au lieu de le laisser faire le travail. Je voudrais faire comme ceci:Il est effectivement plus pratique d'utiliser une formule pour votre avion, qui ne dépend pas du coefficient de
z
n'étant pas nulle, c'est à dire utilisera*x + b*y + c*z = 1
. Vous pouvez même calculera
,b
etc
faire:À projeter des points sur un plan, à l'aide de mon alternative équation, le vecteur
(a, b, c)
est perpendiculaire au plan. Il est facile de vérifier que le point(a, b, c) /(a**2+b**2+c**2)
est dans l'avion, de sorte que la projection peut être fait par le référencement de tous points à ce point sur le plan, la projection des points sur la normale vecteur, soustraire que la projection de points, puis de référencement de retour à l'origine. Vous pouvez le faire comme suit:Alors maintenant, vous pouvez faire quelque chose comme:
Je viens de réaliser que le code ci-dessus est en supposant que votre plan ne passant pas par l'origine, c'est à dire qu'il ne peut pas être utilisé pour projeter sur un plan d'équation
a*x + b*y + c*z = 0
. Pas sûr de la façon de contourner facilement sans trop de complications, mais il faut être conscient de cette mise en garde importante.oh merci, hier j'ai testé uniquement avec un plan qui passe par l'origine, mais vous avez raison: il n'est pas correct pour les avions en dehors de l'origine. j'ai fait la suivante:
calculer la moyenne arithmétique de tous les x,y,z-valeurs; déplacer tous les points de cette valeur (de sorte que le centre de cette scatter-plot passe par l'origine) et puis startet votre code. après que j'ai déménagé tous les points 'en arrière'. Maintenant j'ai un avion qui regarde ok, mais c'est à un mauvais endroit dans mon système de coordonnées. J' pense il est juste à la bonne position en x, mais pas à la bonne y et z de la position de la co-système. A-il quelque chose à faire avec cette ligne:
return np.linalg.lstsq(a, np.ones_like(x))[0]
?OriginalL'auteur Jaime
Vous pouvez tout simplement faire tout ce qui dans des matrices est une option.
Si vous ajoutez vos points de la ligne de vecteurs à une matrice
X
, ety
est un vecteur, alors les paramètres du vecteurbeta
pour la solution des moindres carrés sont:mais il y a un moyen plus facile, si nous voulons faire des projections: décomposition QR nous donne un repère orthonormé matrice de projection, comme
Q.T
, etQ
est lui-même la matrice orthonormale de vecteurs de base. Donc, on peut d'abord formulaireQR
, puis obtenirbeta
, puis utilisezQ.T
à projet de les points.QR:
beta:
Alors maintenant, nous avons
beta
, et nous pouvons projeter les points à l'aide deQ.T
très simplement:Thats it!
Si vous voulez plus d'informations et graphiques piccies et d'autres choses, j'ai fait tout un tas de notes, tout en faisant quelque chose de similaire à: https://github.com/hughperkins/selfstudy-IBP/blob/9dedfbb93f4320ac1bfef60db089ae0dba5e79f6/test_bases.ipynb
(Edit: notez que si vous souhaitez ajouter un biais terme, de sorte que le meilleur ajustement de ne pas avoir à passer par l'origine, vous pouvez simplement ajouter une colonne supplémentaire, avec tous-1s, à
X
, qui agit comme le biais terme/long métrage)OriginalL'auteur Hugh Perkins