Skip to content

Commit

Permalink
Merge pull request #25 from dashidhy/master
Browse files Browse the repository at this point in the history
improve installation, support remote usage
  • Loading branch information
kuixu authored Jun 13, 2020
2 parents 8b6e234 + e837006 commit d54807c
Show file tree
Hide file tree
Showing 7 changed files with 393 additions and 45 deletions.
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,29 @@ kitti
velodyne
```

## Requirements

- opencv
## Install locally on a Ubuntu 16.04 PC with GUI
- start from a new conda enviornment:
```
conda install opencv -c menpo
(base)$ conda create -n kitti_vis python=3.7 # vtk does not support python 3.8
(base)$ conda activate kitti_vis
```
- mayavi, vtk, PIL

- opencv, pillow, scipy, matplotlib
```
(kitti_vis)$ pip install opencv-python pillow scipy matplotlib
```
- install mayavi from conda-forge, this installs vtk and pyqt5 automatically
```
pip install mayavi vtk pillow pyqt5
# or
conda install mayavi vtk pillow pyqt5
(kitti_vis)$ conda install mayavi -c conda-forge
```
- test installation
```
(kitti_vis)$ python kitti_object.py --show_lidar_with_depth --img_fov --const_box --vis
```

**Note: the above installation has been tested not work on MacOS.**

## Install remotely
Please refer to the [jupyter](jupyter/) folder for installing on a remote server and visulizing in Jupyter Notebook.

## Visualization

Expand Down
38 changes: 38 additions & 0 deletions jupyter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Install remotely on a Ubuntu 16.04 server and visulize by Jupyter Notebook
## Install mayavi
- remote servers usually lack GUI supports, so first some libraries and backends should be installed
```
(base)$ sudo apt-get update && sudo apt-get install libgl1-mesa-glx xvfb
```
- install like locally, add [xvfbwrapper](https://github.com/enthought/mayavi/issues/477#issuecomment-477653210)
```
(base)$ conda create -n kitti_vis python=3.7
(base)$ conda activate kitti_vis
(kitti_vis)$ pip install opencv-python pillow scipy matplotlib xvfbwrapper
(kitti_vis)$ conda install mayavi -c conda-forge
```
- install jupyter notebook
```
(kitti_vis)$ pip install notebook
```
- install ipywidgets and ipyevents, enable them as notebook extensions
```
(kitti_vis)$ pip install ipywidgets ipyevents
(kitti_vis)$ jupyter nbextension enable --py --sys-prefix widgetsnbextension
(kitti_vis)$ jupyter nbextension enable --py --sys-prefix ipyevents
```
- install and enable mayavi extension
```
(kitti_vis)$ jupyter nbextension install --py --sys-prefix mayavi
(kitti_vis)$ jupyter nbextension enable --py --sys-prefix mayavi
```
- to test on Jupyter notebook, first set [ETS_TOOLKIT](https://github.com/enthought/mayavi/issues/439#issuecomment-251703994)
```
(kitti_vis)$ export ETS_TOOLKIT='null'
```
- then you can test mayavi intallation by [this notebook](test_mayavi.ipynb), which should show an interactive 3D curve

## Use Jupyter Notebook for kitti visulization
- Here is a simple [demo](../notebook_demo.ipynb).

**Note: the above installation is tested successful on [an official PyTorch docker image](https://hub.docker.com/layers/pytorch/pytorch/1.5-cuda10.1-cudnn7-devel/images/sha256-449d5b98aa911955f55cb3ab413b81b34861ab5f4244519099328df282275690?context=explore).**
68 changes: 68 additions & 0 deletions jupyter/test_mayavi.ipynb

Large diffs are not rendered by default.

49 changes: 27 additions & 22 deletions kitti_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_image(self, idx):
img_filename = os.path.join(self.image_dir, "%06d.png" % (idx))
return utils.load_image(img_filename)

def get_lidar(self, idx, dtype=np.float64, n_vec=4):
def get_lidar(self, idx, dtype=np.float32, n_vec=4):
assert idx < self.num_samples
lidar_filename = os.path.join(self.lidar_dir, "%06d.bin" % (idx))
print(lidar_filename)
Expand Down Expand Up @@ -170,7 +170,7 @@ def viz_kitti_video():
video_path,
)
print(len(dataset))
for i in range(len(dataset)):
for _ in range(len(dataset)):
img = dataset.get_image(0)
pc = dataset.get_lidar(0)
cv2.imshow("video", img)
Expand All @@ -186,7 +186,7 @@ def show_image_with_boxes(img, objects, calib, show3d=True, depth=None):
""" Show image with 2D bounding boxes """
img1 = np.copy(img) # for 2d bbox
img2 = np.copy(img) # for 3d bbox
img3 = np.copy(img) # for 3d bbox
#img3 = np.copy(img) # for 3d bbox
for obj in objects:
if obj.type == "DontCare":
continue
Expand All @@ -197,7 +197,7 @@ def show_image_with_boxes(img, objects, calib, show3d=True, depth=None):
(0, 255, 0),
2,
)
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_2d, _ = utils.compute_box_3d(obj, calib.P)
img2 = utils.draw_projected_box3d(img2, box3d_pts_2d)

# project
Expand All @@ -215,6 +215,8 @@ def show_image_with_boxes(img, objects, calib, show3d=True, depth=None):
cv2.imshow("3dbox", img2)
if depth is not None:
cv2.imshow("depth", depth)

return img1, img2


def show_image_with_boxes_3type(img, objects, calib, objects2d, name, objects_pred):
Expand Down Expand Up @@ -357,6 +359,8 @@ def show_lidar_with_depth(
):
""" Show all LiDAR points.
Draw 3d box in LiDAR point cloud (in velo coord system) """
if "mlab" not in sys.modules:
import mayavi.mlab as mlab
from viz_util import draw_lidar_simple, draw_lidar, draw_gt_boxes3d

print(("All point num: ", pc_velo.shape[0]))
Expand Down Expand Up @@ -394,7 +398,7 @@ def show_lidar_with_depth(
if obj.type == "DontCare":
continue
# Draw 3d bounding box
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
print("box3d_pts_3d_velo:")
print(box3d_pts_3d_velo)
Expand All @@ -407,13 +411,13 @@ def show_lidar_with_depth(
if obj.type == "DontCare":
continue
# Draw 3d bounding box
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
print("box3d_pts_3d_velo:")
print(box3d_pts_3d_velo)
draw_gt_boxes3d([box3d_pts_3d_velo], fig=fig, color=color)
# Draw heading arrow
ori3d_pts_2d, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
_, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
ori3d_pts_3d_velo = calib.project_rect_to_velo(ori3d_pts_3d)
x1, y1, z1 = ori3d_pts_3d_velo[0, :]
x2, y2, z2 = ori3d_pts_3d_velo[1, :]
Expand Down Expand Up @@ -530,7 +534,7 @@ def show_lidar_with_boxes(
if obj.type == "DontCare":
continue
# Draw 3d bounding box
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
print("box3d_pts_3d_velo:")
print(box3d_pts_3d_velo)
Expand All @@ -550,10 +554,9 @@ def show_lidar_with_boxes(
print("dep_pc_velo:", dep_pc_velo)

draw_lidar(dep_pc_velo, fig=fig, pts_color=(1, 1, 1))
#

# Draw heading arrow
ori3d_pts_2d, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
_, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
ori3d_pts_3d_velo = calib.project_rect_to_velo(ori3d_pts_3d)
x1, y1, z1 = ori3d_pts_3d_velo[0, :]
x2, y2, z2 = ori3d_pts_3d_velo[1, :]
Expand All @@ -572,13 +575,13 @@ def show_lidar_with_boxes(
if obj.type == "DontCare":
continue
# Draw 3d bounding box
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
print("box3d_pts_3d_velo:")
print(box3d_pts_3d_velo)
draw_gt_boxes3d([box3d_pts_3d_velo], fig=fig, color=color)
# Draw heading arrow
ori3d_pts_2d, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
_, ori3d_pts_3d = utils.compute_orientation_3d(obj, calib.P)
ori3d_pts_3d_velo = calib.project_rect_to_velo(ori3d_pts_3d)
x1, y1, z1 = ori3d_pts_3d_velo[0, :]
x2, y2, z2 = ori3d_pts_3d_velo[1, :]
Expand Down Expand Up @@ -629,14 +632,15 @@ def stat_lidar_with_boxes(pc_velo, objects, calib):
for obj in objects:
if obj.type == "DontCare":
continue
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
v_l, v_w, v_h, _ = get_velo_whl(box3d_pts_3d_velo, pc_velo)
print("%.4f %.4f %.4f %s" % (v_w, v_h, v_l, obj.type))


def show_lidar_on_image(pc_velo, img, calib, img_width, img_height):
""" Project LiDAR points to image """
img = np.copy(img)
imgfov_pc_velo, pts_2d, fov_inds = get_lidar_in_image_fov(
pc_velo, calib, 0, 0, img_width, img_height, True
)
Expand Down Expand Up @@ -671,7 +675,7 @@ def show_lidar_topview_with_boxes(pc_velo, objects, calib, objects_pred=None):
# gt

def bbox3d(obj):
box3d_pts_2d, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
_, box3d_pts_3d = utils.compute_box_3d(obj, calib.P)
box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d)
return box3d_pts_3d_velo

Expand All @@ -692,12 +696,13 @@ def bbox3d(obj):
)

cv2.imshow("top_image", top_image)
return top_image


def dataset_viz(root_dir, args):
dataset = kitti_object(root_dir, split=args.split, args=args)
## load 2d detection results
objects2ds = read_det_file("box2d.list")
#objects2ds = read_det_file("box2d.list")

if args.show_lidar_with_depth:
import mayavi.mlab as mlab
Expand All @@ -713,7 +718,7 @@ def dataset_viz(root_dir, args):
objects = dataset.get_label_objects(data_idx)
else:
objects = []
objects2d = objects2ds[data_idx]
#objects2d = objects2ds[data_idx]

objects_pred = None
if args.pred:
Expand All @@ -736,11 +741,11 @@ def dataset_viz(root_dir, args):
pc_velo = dataset.get_lidar(data_idx, dtype, n_vec)[:, 0:n_vec]
calib = dataset.get_calibration(data_idx)
img = dataset.get_image(data_idx)
img_height, img_width, img_channel = img.shape
img_height, img_width, _ = img.shape
print(data_idx, "image shape: ", img.shape)
print(data_idx, "velo shape: ", pc_velo.shape)
if args.depth:
depth, is_exist = dataset.get_depth(data_idx)
depth, _ = dataset.get_depth(data_idx)
print(data_idx, "depth shape: ", depth.shape)
else:
depth = None
Expand Down Expand Up @@ -806,9 +811,9 @@ def depth_to_lidar_format(root_dir, args):

pc_velo = dataset.get_lidar(data_idx)[:, 0:4]
calib = dataset.get_calibration(data_idx)
depth, is_exist = dataset.get_depth(data_idx)
depth, _ = dataset.get_depth(data_idx)
img = dataset.get_image(data_idx)
img_height, img_width, img_channel = img.shape
img_height, img_width, _ = img.shape
print(data_idx, "image shape: ", img.shape)
print(data_idx, "velo shape: ", pc_velo.shape)
print(data_idx, "depth shape: ", depth.shape)
Expand All @@ -826,12 +831,12 @@ def depth_to_lidar_format(root_dir, args):
depth,
constraint_box=args.const_box,
)
input_str = raw_input()
#input_str = raw_input()


def read_det_file(det_filename):
""" Parse lines in 2D detection output files """
det_id2str = {1: "Pedestrian", 2: "Car", 3: "Cyclist"}
#det_id2str = {1: "Pedestrian", 2: "Car", 3: "Cyclist"}
objects = {}
with open(det_filename, "r") as f:
for line in f.readlines():
Expand Down
19 changes: 8 additions & 11 deletions kitti_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,17 +414,14 @@ def load_velo_scan(velo_filename, dtype=np.float32, n_vec=4):
return scan


def lidar_to_top_coords(x, y, z=None):
if 0:
return x, y
else:
# print("TOP_X_MAX-TOP_X_MIN:",TOP_X_MAX,TOP_X_MIN)
X0, Xn = 0, int((TOP_X_MAX - TOP_X_MIN) // TOP_X_DIVISION) + 1
Y0, Yn = 0, int((TOP_Y_MAX - TOP_Y_MIN) // TOP_Y_DIVISION) + 1
xx = Yn - int((y - TOP_Y_MIN) // TOP_Y_DIVISION)
yy = Xn - int((x - TOP_X_MIN) // TOP_X_DIVISION)
def lidar_to_top_coords(x, y):
# print("TOP_X_MAX-TOP_X_MIN:",TOP_X_MAX,TOP_X_MIN)
Xn = int((TOP_X_MAX - TOP_X_MIN) // TOP_X_DIVISION) + 1
Yn = int((TOP_Y_MAX - TOP_Y_MIN) // TOP_Y_DIVISION) + 1
xx = Yn - int((y - TOP_Y_MIN) // TOP_Y_DIVISION)
yy = Xn - int((x - TOP_X_MIN) // TOP_X_DIVISION)

return xx, yy
return xx, yy


def lidar_to_top(lidar):
Expand Down Expand Up @@ -789,7 +786,7 @@ def linear_regression(train_x, train_y, test_x):

# dump fit result
dump_fit_func(w_fit)
fit_cost = dump_fit_cost(w_fit, train_x, train_y)
dump_fit_cost(w_fit, train_x, train_y)

# test set
# test_x = np.array(np.arange(train_x.min(), train_x.max(), 1.0))
Expand Down
230 changes: 230 additions & 0 deletions notebook_demo.ipynb

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions viz_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def rotation_matrix_numpy0(axis, theta, dtype=None):


def rotation_matrix_numpy(axis, theta):
mat = np.eye(3, 3)

axis = axis / np.sqrt(np.dot(axis, axis))
a = np.cos(theta / 2.0)
b, c, d = -axis * np.sin(theta / 2.0)
Expand Down Expand Up @@ -261,8 +261,8 @@ def draw_lidar(
TOP_Y_MAX = 20
TOP_X_MIN = 0
TOP_X_MAX = 40
TOP_Z_MIN = -2.0
TOP_Z_MAX = 0.4
#TOP_Z_MIN = -2.0
#TOP_Z_MAX = 0.4

x1 = TOP_X_MIN
x2 = TOP_X_MAX
Expand Down

0 comments on commit d54807c

Please sign in to comment.