2017-02-20 34 views
3

У меня есть миллионы xyz-координат из нескольких файлов облаков точек, которые я храню внутри двумерного массива numpy: [[x1, y1, z1], [x2, y2, z2],..., [xn, yn, zn]].Поиск точек в ограничивающей рамке с numpy

Я хочу отфильтровать все точки, которые находятся внутри определенной ограничивающей рамки, описываемой четырьмя координатами [[x1, y1], [x2, y2]] т. Е. Нижним левым и верхним правыми координатами прямоугольника.

Я уже нашел следующий фрагмент кода для фильтрации координат с numpy, и это почти то, что я хочу. Единственное различие - (если я правильно понимаю), что у моего двумерного массива также есть z-координаты.

import random 
import numpy as np 

points = [(random.random(), random.random()) for i in range(100)] 

bx1, bx2 = sorted([random.random(), random.random()]) 
by1, by2 = sorted([random.random(), random.random()]) 

pts = np.array(points) 
ll = np.array([bx1, by1]) # lower-left 
ur = np.array([bx2, by2]) # upper-right 

inidx = np.all(np.logical_and(ll <= pts, pts <= ur), axis=1) 
inbox = pts[inidx] 
outbox = pts[np.logical_not(inidx)] 

Как бы я должен modifiy код, чтобы заставить его работать с АБВ-координатами, чтобы быть отфильтрованы ограничивающего параллелепипеда, описанного с двумя XY-координат?

ответ

3

Выберите X и Y координаты ваших точек:

xy_pts = pts[:,[0,1]] 

Теперь просто использовать xy_pts вместо pts в сравнениях:

inidx = np.all((ll <= xy_pts) & (xy_pts <= ur), axis=1) 
+0

Но, как и я потерял бы г-информацию, или нет? Мне определенно нужно сохранить их для последующих вычислений. – conste

+0

@conste Вы будете использовать оригинальные 3D 'pts' для создания' inbox'. – DyZ

1

Я пишу Python library for working with point clouds, и у меня есть это что я думаю, что это должно сработать для вас:

def bounding_box(points, min_x=-np.inf, max_x=np.inf, min_y=-np.inf, 
         max_y=np.inf, min_z=-np.inf, max_z=np.inf): 
    """ Compute a bounding_box filter on the given points 

    Parameters 
    ----------       
    points: (n,3) array 
     The array containing all the points's coordinates. Expected format: 
      array([ 
       [x1,y1,z1], 
       ..., 
       [xn,yn,zn]]) 

    min_i, max_i: float 
     The bounding box limits for each coordinate. If some limits are missing, 
     the default values are -infinite for the min_i and infinite for the max_i. 

    Returns 
    ------- 
    bb_filter : boolean array 
     The boolean mask indicating wherever a point should be keeped or not. 
     The size of the boolean mask will be the same as the number of given points. 

    """ 

    bound_x = np.logical_and(points[:, 0] > min_x, points[:, 0] < max_x) 
    bound_y = np.logical_and(points[:, 1] > min_y, points[:, 1] < max_y) 
    bound_z = np.logical_and(points[:, 2] > min_z, points[:, 2] < max_z) 

    bb_filter = np.logical_and(bound_x, bound_y, bound_z) 

    return bb_filter 

Вот пример того, что вы спрашиваете:

10 миллионов пунктов:

points = np.random.rand(10000000, 3) 

прямоугольник в формате вы указываете:

rectangle = np.array([[0.2, 0.2], 
        [0.4, 0.4]]) 

Распакуйте прямоугольник:

min_x = rectangle[:,0].min() 
max_x = rectangle[:,0].max() 
min_y = rectangle[:,1].min() 
max_y = rectangle[:,1].max() 

Получите метки булевого блока в поле:

%%timeit 
inside_box = bounding_box(points, min_x=min_x, max_x=max_x, min_y=min_y, max_y=max_y) 
1 loop, best of 3: 247 ms per loop 

Таким образом, вы можете использовать массив следующим образом:

points_inside_box = points[inside_box] 
points_outside_box = points[~inside_box] 

 Смежные вопросы

  • Нет связанных вопросов^_^