forked from tensorflow/models
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdepth_utils.py
96 lines (89 loc) · 3.6 KB
/
depth_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# Copyright 2016 The TensorFlow Authors All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Utilities for processing depth images.
"""
import numpy as np
import src.rotation_utils as ru
import src.utils as utils
def get_camera_matrix(width, height, fov):
"""Returns a camera matrix from image size and fov."""
xc = (width-1.) / 2.
zc = (height-1.) / 2.
f = (width / 2.) / np.tan(np.deg2rad(fov / 2.))
camera_matrix = utils.Foo(xc=xc, zc=zc, f=f)
return camera_matrix
def get_point_cloud_from_z(Y, camera_matrix):
"""Projects the depth image Y into a 3D point cloud.
Inputs:
Y is ...xHxW
camera_matrix
Outputs:
X is positive going right
Y is positive into the image
Z is positive up in the image
XYZ is ...xHxWx3
"""
x, z = np.meshgrid(np.arange(Y.shape[-1]),
np.arange(Y.shape[-2]-1, -1, -1))
for i in range(Y.ndim-2):
x = np.expand_dims(x, axis=0)
z = np.expand_dims(z, axis=0)
X = (x-camera_matrix.xc) * Y / camera_matrix.f
Z = (z-camera_matrix.zc) * Y / camera_matrix.f
XYZ = np.concatenate((X[...,np.newaxis], Y[...,np.newaxis],
Z[...,np.newaxis]), axis=X.ndim)
return XYZ
def make_geocentric(XYZ, sensor_height, camera_elevation_degree):
"""Transforms the point cloud into geocentric coordinate frame.
Input:
XYZ : ...x3
sensor_height : height of the sensor
camera_elevation_degree : camera elevation to rectify.
Output:
XYZ : ...x3
"""
R = ru.get_r_matrix([1.,0.,0.], angle=np.deg2rad(camera_elevation_degree))
XYZ = np.matmul(XYZ.reshape(-1,3), R.T).reshape(XYZ.shape)
XYZ[...,2] = XYZ[...,2] + sensor_height
return XYZ
def bin_points(XYZ_cms, map_size, z_bins, xy_resolution):
"""Bins points into xy-z bins
XYZ_cms is ... x H x W x3
Outputs is ... x map_size x map_size x (len(z_bins)+1)
"""
sh = XYZ_cms.shape
XYZ_cms = XYZ_cms.reshape([-1, sh[-3], sh[-2], sh[-1]])
n_z_bins = len(z_bins)+1
map_center = (map_size-1.)/2.
counts = []
isvalids = []
for XYZ_cm in XYZ_cms:
isnotnan = np.logical_not(np.isnan(XYZ_cm[:,:,0]))
X_bin = np.round(XYZ_cm[:,:,0] / xy_resolution + map_center).astype(np.int32)
Y_bin = np.round(XYZ_cm[:,:,1] / xy_resolution + map_center).astype(np.int32)
Z_bin = np.digitize(XYZ_cm[:,:,2], bins=z_bins).astype(np.int32)
isvalid = np.array([X_bin >= 0, X_bin < map_size, Y_bin >= 0, Y_bin < map_size,
Z_bin >= 0, Z_bin < n_z_bins, isnotnan])
isvalid = np.all(isvalid, axis=0)
ind = (Y_bin * map_size + X_bin) * n_z_bins + Z_bin
ind[np.logical_not(isvalid)] = 0
count = np.bincount(ind.ravel(), isvalid.ravel().astype(np.int32),
minlength=map_size*map_size*n_z_bins)
count = np.reshape(count, [map_size, map_size, n_z_bins])
counts.append(count)
isvalids.append(isvalid)
counts = np.array(counts).reshape(list(sh[:-3]) + [map_size, map_size, n_z_bins])
isvalids = np.array(isvalids).reshape(list(sh[:-3]) + [sh[-3], sh[-2], 1])
return counts, isvalids