Ich habe kürzlich Pytorch gelernt, also werde ich damit spielen.
Alles was Sie tun müssen, ist die Punkte auszurichten.
Zu diesem Zweck hat icp ein Bild, das dazu neigt, in eine lokale Lösung zu fallen, aber Läuft die hochmoderne Optimierungsfunktion von pytorch nicht ziemlich gut? Ich werde es mit der flauschigen Erwartung versuchen.
Der Fluss ist wie folgt.
für jeden Punkt der Punktgruppe B.
1.Transformationsmatrix$P = [R|t]$Ist definiert.
Die Ausrichtung erfolgt durch Optimierung dieses Parameters.
2.Berechnen Sie die nächste Nachbarschaft der Punktgruppe und erhalten Sie die Menge der nächsten Punkte.
3.Transformationsmatrix$P$Die Punkte der Punktgruppe B, zu denen
Die Punkte, die der Punktgruppe A am nächsten liegen, diese beiden, werden von der Verlustfunktion bewertet.
4.Optimierungsprozess
Optimierte Transformationsmatrix$P$Bewerben und erneut von 1 ausführen
Überprüfen Sie mit dem folgenden Ablauf.
1.Bereiten Sie zwei identische Punktgruppen vor und bewegen Sie sich nur (Anpassen der 3D-Parameter)
2.Bereiten Sie zwei identische Punktgruppen vor und führen Sie nur eine Drehung durch (Anpassung der 9-dimensionalen Parameter).
3.Bereiten Sie zwei identische Punktgruppen vor und drehen / bewegen Sie sich (12-dimensionale Parametereinstellung)
3.Bereiten Sie zwei verschiedene Punktgruppen vor und drehen / bewegen Sie sich (12-dimensionale Parametereinstellung)
3.Fügen Sie der anderen Seite Rauschen hinzu, bereiten Sie zwei verschiedene Punktgruppen vor und drehen / bewegen Sie sich (12-dimensionale Parametereinstellung)
Ich habe das geschrieben, aber ich habe in der ersten Phase versagt. Ich bin noch nicht an Pytorch gewöhnt, also fehlt vielleicht etwas.
tetst.py
import copy
import numpy as np
import open3d as o3d
import random
import math
import torch.nn as nn
import torch.nn.functional as F
import torch
import torch.optim as optim
import matplotlib.pyplot as plt
epoch = 1000
def getPLYfromNumpy(nplist):
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(nplist)
return pcd
def write_point_cloud(path, pcl):
assert o3d.io.write_point_cloud(path, pcl), "write pcl error : " + path
def read_point_cloud(path):
pcl = o3d.io.read_point_cloud(path)
if len(pcl.points) == 0: assert False, "load pcl error : " + path
return pcl
def Register_EachPoint_RT(pclA, pclB,testP,criterion,optimizer):
history = {
'train_loss': [],
'test_acc': [],
}
transP = torch.tensor(
[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
requires_grad=True)
params = [transP]
optimizer = optimizer(params)
kd_tree_A = o3d.geometry.KDTreeFlann(pclA)
cnt = 0
#Versuchen Sie es in Punkten
for j in range(epoch):
for didx in range(len(pclB.points)):
cnt += 1
optimizer.zero_grad()
#Nächste Berechnung
[_, Aidx1, _] = kd_tree_A.search_knn_vector_3d(pclB.points[didx], 1)
ptA_sample = pclA.points[Aidx1[0]]
ptB_sample = pclB.points[didx]
#Versteckte Koordinaten
ptA_sample = np.array([ptA_sample[0], ptA_sample[1], ptA_sample[2], 1])
ptB_sample = np.array([ptB_sample[0], ptB_sample[1], ptB_sample[2], 1])
ptA_sample = ptA_sample.reshape(4, 1)
ptB_sample = ptB_sample.reshape(4, 1)
A_tor = torch.tensor(ptA_sample.tolist(), requires_grad=False)
B_tor = torch.tensor(ptB_sample.tolist(), requires_grad=False)
answer = A_tor
output = torch.mm(transP, B_tor)
loss = criterion(answer, output)
loss.backward()
optimizer.step()
# print( j, cnt, " :Error= ", loss.item(),"\n",transP)
ls = np.linalg.norm(testP - transP.to('cpu').detach().numpy().copy())
history['train_loss'].append(loss)
history['test_acc'].append(ls)
print(" :Error= ", loss.item(),"\t Fehler mit der richtigen Konvertierungsmatrix= ",ls)
plt.figure()
plt.plot(range(1, cnt + 1), history['train_loss'], label='train_loss')
plt.xlabel('train_loss')
plt.legend()
plt.savefig('train_loss.png')
plt.figure()
plt.plot(range(1, cnt + 1), history['test_acc'], label='test_acc')
plt.xlabel('test_acc')
plt.legend()
plt.savefig('test_acc.png')
return transP
def Register_EachPoint_T(pclA, pclB,testP,criterion,optimizer):
history = {
'train_loss': [],
'test_acc': [],
}
transP = torch.tensor([[0.0], [0.0], [0.0]],requires_grad=True)
params = [transP]
optimizer = optimizer(params)
kd_tree_A = o3d.geometry.KDTreeFlann(pclA)
cnt = 0
#Versuchen Sie es in Punkten
for j in range(epoch):
for didx in range(len(pclB.points)):
cnt += 1
optimizer.zero_grad()
#Holen Sie sich die Punkte der Punktgruppe A, die jedem Punkt der Punktgruppe B am nächsten liegen
[_, Aidx1, _] = kd_tree_A.search_knn_vector_3d(pclB.points[didx], 1)
ptA_sample = pclA.points[Aidx1[0]]
ptB_sample = pclB.points[didx]
#Versteckte Koordinaten
ptA_sample = np.array([ptA_sample[0], ptA_sample[1], ptA_sample[2]])
ptB_sample = np.array([ptB_sample[0], ptB_sample[1], ptB_sample[2]])
ptA_sample = ptA_sample.reshape(3, 1)
ptB_sample = ptB_sample.reshape(3, 1)
#Konvertieren Sie jeden Punkt in Tensor
A_tor = torch.tensor(ptA_sample.tolist(), requires_grad=False)
B_tor = torch.tensor(ptB_sample.tolist(), requires_grad=False)
#Passen Sie Punktgruppe B an Punktgruppe A an.
answer = A_tor
output = (B_tor + transP)
#Verlustberechnung->Optimierung
loss = criterion(answer, output)
loss.backward()
optimizer.step()
#Vergleich mit der richtigen Umrechnungsmatrix. (0 ist wünschenswert)
ls = np.linalg.norm(testP - transP.to('cpu').detach().numpy().copy())
history['train_loss'].append(loss)
history['test_acc'].append(ls)
print(" :Error= ", loss.item(), "\t Fehler mit der richtigen Konvertierungsmatrix= ", ls)
#Reflektieren Sie das Anpassungsergebnis->Berechnung des nächsten Nachbarn erneut in der nächsten Schleife
nptransP = transP.to('cpu').detach().numpy().copy().reshape(1,3)
pclB = getPLYfromNumpy(pclB.points + nptransP)
plt.figure()
plt.plot(range(1, cnt + 1), history['train_loss'], label='train_loss')
plt.xlabel('train_loss')
plt.legend()
plt.savefig('train_loss.png')
plt.figure()
plt.plot(range(1, cnt + 1), history['test_acc'], label='test_acc')
plt.xlabel('test_acc')
plt.legend()
plt.savefig('test_acc.png')
return transP
POINT_NUM = 1024
# http://graphics.stanford.edu/data/3Dscanrep/
pclA = read_point_cloud("bun000.ply")
A = np.array(pclA.points)
A = np.array(random.sample(A.tolist(), POINT_NUM))
#Eine Gruppe von Punkten mit einem etwas höheren Schwierigkeitsgrad. Vielleicht geht das noch nicht ...
# pclB = read_point_cloud("bun045.ply")
# B = np.array(pclB.points)
# B = np.array(random.sample(B.tolist(), POINT_NUM))
# #Rauschen hinzufügen
# B += np.random.randn(POINT_NUM, 3) * 0.005
# #Gewähren von Unordnung (außer Betrieb) von Punktgruppen
# np.random.shuffle(B)
# pclB_sample = getPLYfromNumpy(B)
pclA_sample = getPLYfromNumpy(A)
T_Projection = np.array([[1, 0, 0, 0.5],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]])
T_translation = np.array([[T_Projection[0][3]], [T_Projection[1][3]], [T_Projection[2][3]]])
pclA_trans_sample = getPLYfromNumpy(A).transform(T_Projection)
write_point_cloud("A_before.ply", pclA_sample)
write_point_cloud("A_rot_before.ply", pclA_trans_sample)
def testEstimateT(pclA_sample,pclA_trans_sample,T_translation):
optimizer = optim.Adam
# MSELoss
transP = Register_EachPoint_T(pclA_sample, pclA_trans_sample, T_translation, nn.MSELoss(),optimizer)
T_res = np.array([[1, 0, 0, transP[0]],
[0, 1, 0, transP[1]],
[0, 0, 1, transP[2]],
[0, 0, 0, 1]])
pclA_res = copy.copy(pclA_trans_sample)
pclA_res = pclA_res.transform(T_res)
write_point_cloud("TOnlytest_A_rot_after_MSELoss.ply", pclA_res)
# # L1Loss
# transP = Register_EachPoint_T(pclA_sample, pclA_trans_sample, T_translation, nn.L1Loss(),optimizer)
# T_res = np.array([[1, 0, 0, transP[0]],
# [0, 1, 0, transP[1]],
# [0, 0, 1, transP[2]],
# [0, 0, 0, 1]])
# pclA_res = copy.copy(pclA_trans_sample)
# pclA_res = pclA_res.transform(T_res)
# write_point_cloud("TOnlytest_A_rot_after_L1Loss.ply", pclA_res)
def testEstimateRT(pclA_sample,pclA_trans_sample,T_Projection):
optimizer = optim.Adam
# MSELoss
transP = Register_EachPoint_RT(pclA_sample, pclA_trans_sample, T_Projection, nn.MSELoss(),optimizer)
transP = transP.to('cpu').detach().numpy().copy()
pclA_res = copy.copy(pclA_trans_sample)
pclA_res = pclA_res.transform(transP)
write_point_cloud("RTtest_A_rot_after_MSELoss.ply", pclA_res)
testEstimateT(pclA_sample, pclA_trans_sample, T_translation)
# testEstimateRT(pclA_sample, pclA_trans_sample, T_Projection)
exit()
Sehen wir uns das Ausgabeergebnis der Verlustfunktion an. Betrachtet man dies allein, so scheint es, als würde es im Handumdrehen gegen 0 konvergieren.
Und dies ist ein Vergleich der durch Optimierung ausgegebenen Konvertierungsmatrix und der Konvertierungsmatrix der richtigen Antwort.
... Ich glaube, ich bin zuerst etwas niedriger geworden, aber ich habe die ganze Zeit Hunger. Es ist ein großer Fehler von 0,5. Ich gebe auch eine Gruppe von Punkten aus, aber ich werde sie weglassen, weil sie nur ein wenig näher war.
Es gibt keinen Ausreißer und es gibt nur 3 Dimensionen, aber warum ... Ich habe das Gefühl, ich mache einfach einen Fehler bei der Verwendung von Pytorch. Wenn Sie wissen, kontaktieren Sie mich bitte.
Als nächstes werden wir PointNet LK untersuchen, eine Erweiterung des T-Netzes von PointNet. https://github.com/wentaoyuan/it-net https://www.slideshare.net/naoyachiba18/pointnetlk-robust-efficient-point-cloud-registration-using-pointnet-167874587