Numpy облако точек на изображение - PullRequest
4 голосов
/ 12 марта 2020

У меня есть облако точек, которое выглядит примерно так:

The point cloud

Красные точки - это точки, черные точки - красные точки проецируется на плоскость xy . Хотя это не видно на графике, каждая точка также имеет значение, которое добавляется к данному пикселю, когда точка перемещается в плоскость xy. Точки представлены массивом numpy (np) следующим образом:

points=np.array([[x0,y0,z0,v0],[x1,y1,z1,v1],...[xn,yn,zn,vn]])

Очевидный способ поместить эти точки в какое-либо изображение - через простой l oop, например:

image=np.zeros(img_size)

for point in points:
    #each point = [x,y,z,v]
    image[tuple(point[0:2])] += point[3]

Теперь это работает нормально, но очень медленно. Поэтому мне было интересно, есть ли какой-нибудь способ использовать векторизацию, нарезку и другие хитрые хитрые / python трюки, чтобы ускорить его, поскольку на самом деле мне приходилось делать это много раз для больших облаков точек. Я придумал что-то, используя np.put:

def points_to_image(xs, ys, vs, img_size):
    img = np.zeros(img_size)
    coords = np.stack((ys, xs))
    #put the 2D coordinates into linear array coordinates
    abs_coords = np.ravel_multi_index(coords, img_size)
    np.put(img, abs_coords, ps)
    return img

(в этом случае точки предварительно разбиваются на векторы, содержащие компоненты x, y и v). Хотя это работает нормально, оно, конечно, только ставит последнюю точку на каждый данный пиксель, то есть не является аддитивным.

Большое спасибо за вашу помощь!

1 Ответ

4 голосов
/ 12 марта 2020

Предоставлено @Paul Panzer:

def points_to_image(xs, ys, ps, img_size):
    coords = np.stack((ys, xs))
    abs_coords = np.ravel_multi_index(coords, img_size)
    img = np.bincount(abs_coords, weights=ps, minlength=img_size[0]*img_size[1])
    img = img.reshape(img_size)

На моей машине версия l oop принимает 0.4432s против 0.0368s с использованием векторизации. Так что аккуратное ускорение в 12 раз.

============ РЕДАКТИРОВАТЬ ============

Быстрое обновление: с помощью факела .. .

def points_to_image_torch(xs, ys, ps, sensor_size=(180, 240)):
    xt, yt, pt = torch.from_numpy(xs), torch.from_numpy(ys), torch.from_numpy(ps)
    img = torch.zeros(sensor_size)
    img.index_put_((yt, xt), pt, accumulate=True)
    return img

Я дошел до 0.00749. И это все еще происходит на процессоре, так что 59-кратное ускорение против python l oop. У меня также был go при запуске его на GPU, похоже, что скорость его работы не имеет значения, я думаю, с accumulate=True он, вероятно, использует какую-то атомарность на GPU, которая замедляет все это.

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