Проецирование KITTI velodyne на изображение дает узкую полосу - PullRequest
0 голосов
/ 25 ноября 2018

Я пытаюсь проецировать KITTI velodyne на изображения с левой камеры.Я следовал за README в KITTI devkit, но результат выключен - точки проецируются в виде узкой полосы в верхней части изображения.Похоже, что полоса имеет некоторое распределение, поэтому я подозреваю, что я делаю что-то не так с калибровочными матрицами.Или, может быть, в PIL.ImageDraw.point?

Уравнение проекции, которое я использую, соответствует документации KITTI devkit:

  • x = P2 * R0_rect * Tr_velo_to_cam * y, где
    • y - матрица 4xN с N точками в формате XYZL (L - свечение),
    • Tr_velo_to_cam - 3x4 матрица преобразования скорости в камеру
    • R0_rect - матрица вращения внешней камеры 3x3
    • P2 - матрица проекции внутренней камеры 3x3

Ниже приведен код, STDIO этого, и произведенное изображение.

test.py:

import numpy as np
import os
from PIL import Image, ImageDraw

DATASET_PATH = "<DATASET PATH HERE>"

vld_path = os.path.join(DATASET_PATH, "velodyne/{:06d}.bin")
img_path = os.path.join(DATASET_PATH, "image_2/{:06d}.png")
clb_path = os.path.join(DATASET_PATH, "calib/{:06d}.txt")

frame_num = 58

# Load files
img = Image.open(img_path.format(frame_num))
clb = {}
with open(clb_path.format(frame_num), 'r') as clb_f:
  for line in clb_f:
    calib_line = line.split(':')
    if len(calib_line) < 2:
      continue
    key = calib_line[0]
    value = np.array(list(map(float, calib_line[1].split())))
    value = value.reshape((3, -1))
    clb[key] = value
vld = np.fromfile(vld_path.format(frame_num), dtype=np.float32)
vld = vld.reshape((-1, 4)).T

print("img.shape:", np.shape(img))
print("P2.shape:", clb['P2'].shape)
print("R0_rect.shape:", clb['R0_rect'].shape)
print("Tr_velo_to_cam.shape:", clb['Tr_velo_to_cam'].shape)
print("vld.shape:", vld.shape)

# Reshape calibration files
P2 = clb['P2']
R0 = np.eye(4)
R0[:-1, :-1] = clb['R0_rect']
Tr = np.eye(4)
Tr[:-1, :] = clb['Tr_velo_to_cam']

# Prepare 3d points
pts3d = vld[:, vld[-1, :] > 0].copy()
pts3d[-1, :] = 1

# Project 3d points
pts3d_cam = R0 @ Tr @ pts3d
mask = pts3d_cam[2, :] >= 0  # Z >= 0
pts2d_cam = P2 @ pts3d_cam[:, mask]
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :]

print("pts2d.shape:", pts2d.shape)

# Draw the points
img_draw = ImageDraw.Draw(img)
img_draw.point(pts2d, fill=(255, 0, 0))
img.show()

STDOUT:

$> python ./test.py 
img.shape: (370, 1224, 3)
P2.shape: (3, 4)
R0_rect.shape: (3, 3)
Tr_velo_to_cam.shape: (3, 4)
vld.shape: (4, 115052)
pts2d.shape: (2, 53119)

Произведенное изображение:

Projection fail

1 Ответ

0 голосов
/ 25 ноября 2018

Обнаружена проблема: обратите внимание, что размеры pts2d равны (2, N), что означает, что у него всего N точек.Однако подпрограмма ImageDraw ожидает, что это будет либо вектор строки Nx2, либо 1x2N с чередующимися значениями x и y.Хотя я не мог заставить подпрограмму point работать со входом Nx2, я поместил ее в цикл for (после транспонирования точек), и она сработала.

# ...
pts2d = (pts2d_cam / pts2d_cam[2, :])[:-1, :].T

print("pts2d.shape:", pts2d.shape)

# Draw the points
img_draw = ImageDraw.Draw(img)
for point in pts2d:
  img_draw.point(point, fill=(255, 0, 0))
# ...

Projection successful

...