Как рекурсивно дискретизировать сегменты, если длина сегмента превышает заданное значение c - PullRequest
1 голос
/ 18 февраля 2020

Чтобы повысить эффективность сценария python, я пытаюсь преобразовать сценарий на основе большого количества операций «для l oop» в облаке точек благодаря Numpy для ускорения процесса .

Points Cloud overview and some euclidean distance representation

В двух словах, у меня есть 3d-модель, представленная в виде набора 3d-точек (координаты x, y, z), содержащихся в np .array (размерность: (188706, 3))

[[168.998 167.681   0.]    <-- point 1
 [169.72  167.695   0.]    <-- point 2
 [170.44  167.629   0.]    <-- point 3
 ...
 [148.986 163.271  25.8]    <-- point 188704
 [148.594 163.634  25.8]    <-- point 188705
 [148.547 163.667  25.8]]   <-- point 188706

Каждая пара [[строка x -1] [строка x ]] представляет сегмент в 3D

[[168.998 167.681   0.]    [169.72  167.695   0.]    <-- SEGMENT 1 (points 1 & 2)
 [169.72  167.695   0.]    [170.44  167.629   0.]    <-- SEGMENT 2 (points 2 & 3)
 [170.44  167.629   0.]    [171.149 167.483   0.]    <-- SEGMENT 3 (points 3 & 4)
 ...
 [149.328 162.853  25.8]   [148.986 163.271  25.8]    <-- SEGMENT 94351 (points 188703 & 188704)
 [148.986 163.271  25.8]   [148.594 163.634  25.8]    <-- SEGMENT 94352 (points 18874 & 188705)
 [148.594 163.634  25.8]   [148.547 163.667  25.8]]   <-- SEGMENT 94353 (points 188705 & 188706)

Моя цель - измерить евклидово расстояние между каждой упорядоченной точкой // парой строк (= длина каждого отрезка), чтобы я мог определить, где мне нужно добавить больше точек для представления немного больше поверхность моей 3d модели. Другими словами, если длина сегмента превышает пороговое значение (= 0,5 мм), мне придется дискретизировать этот конкретный сегмент с большим количеством точек и добавить эти дополнительные точки в мое облако точек.

Я имею нашел способ измерить евклидово расстояние рекурсивно между каждой строкой благодаря этому коду:

EuclidianDistance = np.linalg.norm(PtCloud[:-1] - PtCloud[1:],axis=1) 

, который дает этот результат:

[0.72213572 0.72301867 0.72387637 ... 0.54008148 0.5342593  0.05742822]

И я также нашел, как описать сегмент в соответствии с его вершинами (конечностями):

def AddEquidistantPoints(p1, p2, parts):
    return np.stack((np.linspace(p1[0], p2[0], parts + 1), np.linspace(p1[1], p2[1], parts + 1)), axis=-1)

if EuclidianDistance > 0.5mm:
    dist = AddEquidistantPoints(currentRow, previousRow, 10) #10 --> nb subdivisions

Но моя первая проблема заключается в том, что евклидовы расстояния нужно вычислять только в точках, где координаты z равны. Должен ли я разделить мой массив, когда координаты z не равны? С:

PtCloud = np.split(PtCloud, np.where(np.diff(PtCloud[:,2])!=0)[0]+1)

, который дает мне список массивов, поэтому я полагаю, что мне, к сожалению, придется использовать для l oop ...

Вот правильное поведение, представленное в Excel : image

И моя вторая проблема связана с этапом рекурсивной проверки и дискретизации, поскольку я не знаю, как реализовать это в данном конкретном случае. Интересно, есть ли способ сделать это без каких-либо циклов for.

Так что я был бы очень рад, если бы кто-нибудь мог помочь мне решить эту проблему, так как я сейчас "застрял". Это становится очень сложным для меня.

Заранее спасибо, Эрве

1 Ответ

0 голосов
/ 22 февраля 2020

Просто чтобы поделиться с вами, я только что нашел способ решить мою проблему. Вероятно, это не самый эффективный способ сделать это, но он работает.

import numpy as np

print("====================")
print("Initial Points Cloud")
print("====================")

POINTCLOUD = np.array([[168.998, 167.681, 0.],
                       [169.72, 167.695,  0.],
                       [170.44, 167.629,  0.],
                       [171.149, 167.483,  0.],
                       [150.149, 167.483,  4.2],
                       [160.149, 167.483,  4.2],
                       [159.149, 166.483,  4.2],
                       [152.149, 157.483,  7.],
                       [149.328, 162.853, 25.8],
                       [148.986, 163.271, 25.8],
                       [148.594, 163.634, 25.8],
                       [180.547, 170.667, 25.8],
                       [200.547, 190.667, 25.8]])
print(POINTCLOUD)


print("============================================")
print("Reshaped Point Cloud in the form of segments")
print("============================================")
a = np.column_stack((POINTCLOUD[:-1],POINTCLOUD[1:]))
print(a)
b = a.reshape((a.shape[0],2, 3))
#print(b)

print("")
print("*******************************")
print("Non filtered euclidean distance")
print("*******************************")
EuclidianDistance = np.transpose(np.linalg.norm(b[:,0] - b[:,1],axis=1))
print(EuclidianDistance)

print("")
print("****************")
print("Mask computation")
print("****************")
mask = np.transpose([a[:,2] == a[:,5]])
mask2 = [a[:,:] == a[:,:]]*np.transpose([a[:,2] == a[:,5]])



print("")
print(mask2)

print("")
print("***********************************")
print("1rst Filter applyed on points cloud")
print("***********************************")

# b = np.where(mask2,a,0)
# b = np.squeeze(b, axis=0)
b = np.squeeze(np.where(mask2,a,0), axis=0)
print(b)
print("")

b2 = b[np.squeeze(mask2,axis=0),...].reshape((np.sum(mask),b.shape[1]))
print(b2)
print("")
#print(b2.reshape(b2.shape[0],2, 3))

b = b2.reshape(b2.shape[0],2, 3)


print("")
print("***************************************")
print("FIRST EUCLIDEAN DISTANCE FILTERING STEP")
print("***************************************")
EuclidianDistance = np.linalg.norm(b[:,0] - b[:,1],axis=1)
print(EuclidianDistance)

print("")
print("***************************")
print("# THRESHOLD MASK GENERATION")
print("***************************")
threshold = 7
mask_threshold = np.transpose(EuclidianDistance>threshold)
print(mask_threshold)

print("")
print("**********************************")
print("# FINAL FILTERED ECLIDEAN DISTANCE")
print("**********************************")
EuclidianDistance = EuclidianDistance[np.squeeze(mask_threshold),...]
print(EuclidianDistance)

print("")
print("**********************")
print("SEGMENTS TO DISCRETIZE")
print("**********************")
SegmentToDiscretize = b[np.squeeze(mask_threshold),...]
print(SegmentToDiscretize)



print("")
print("******************************")
print("EQUIDISTANT POINTS COMPUTATION")
print("******************************")

nbsubdiv2 = np.transpose(np.ceil(np.array(np.divide(EuclidianDistance,0.7))).astype(int)).reshape((SegmentToDiscretize.shape[0],1))
print(nbsubdiv2)
print(nbsubdiv2.shape)
print(nbsubdiv2[1,0])

print(SegmentToDiscretize.shape)
print(SegmentToDiscretize[:,0])


nbsubdiv = [10,30,10]

addedpoint = np.linspace(SegmentToDiscretize[:,0],SegmentToDiscretize[:,1],nbsubdiv[0], dtype = np.float)
addedpoint = addedpoint.reshape((addedpoint.shape[0]*addedpoint.shape[1],3))
print(np.sort(addedpoint,axis=0))


print("")
print("***********************************")
print("UPDATED POINT CLOUD WITH NEW POINTS")
print("***********************************")
# duplicates are removed with the command np.unique
POINTCLOUD = np.unique(np.append(POINTCLOUD,addedpoint, axis=0),axis=0)
print(POINTCLOUD)

print("")
print("************************")
print("FINAL SORTED POINT CLOUD")
print("************************")
sortedPOINTCLOUD = POINTCLOUD[np.argsort(POINTCLOUD[:, 2])]
print(sortedPOINTCLOUD)
print("***************************")

Пожалуйста, не стесняйтесь добавлять свое собственное предложение, чтобы улучшить его, если хотите. Это будет очень приветствоваться!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...