1
1
import numpy as np
2
- import tensorflow as tf
3
2
from waypoint_grids .uniform_sampling_grid import UniformSamplingGrid
4
3
5
4
@@ -11,36 +10,39 @@ def __init__(self, params):
11
10
# Compute the image size bounds based on the focal length and the field of view
12
11
params = self .compute_image_bounds (params )
13
12
super (ProjectedImageSpaceGrid , self ).__init__ (params )
14
-
13
+
15
14
# Compute the rotation and translation vectors from the world frame to the optical frame and vice-versa
16
15
self .compute_rotation_and_translation_transformations ()
17
-
16
+
18
17
@staticmethod
19
18
def compute_image_bounds (params ):
20
19
"""
21
20
Compute the image size bounds based on the focal length and the field of view.
22
21
"""
23
22
eps = 1e-2
24
23
# The projection point of the outermost point in the filed of view
25
- dx = params .projected_grid_params .f * np .tan (params .projected_grid_params .fov )
26
-
24
+ dx = params .projected_grid_params .f * \
25
+ np .tan (params .projected_grid_params .fov )
26
+
27
27
# Compute x_min and x_max
28
28
x_min = - 1. * dx
29
29
x_max = 1. * dx
30
-
30
+
31
31
# Compute y_min
32
32
if params .projected_grid_params .tilt > params .projected_grid_params .fov :
33
33
y_min = - 1. * dx
34
34
else :
35
35
# An eps is subtracted from the tilt to clip the far end of the camera
36
- y_min = - 1. * params .projected_grid_params .f * np .tan (params .projected_grid_params .tilt - eps )
37
-
36
+ y_min = - 1. * params .projected_grid_params .f * \
37
+ np .tan (params .projected_grid_params .tilt - eps )
38
+
38
39
# Compute y_max
39
- if params .projected_grid_params .tilt + params .projected_grid_params .fov < np .pi / 2 :
40
+ if params .projected_grid_params .tilt + params .projected_grid_params .fov < np .pi / 2 :
40
41
y_max = 1. * dx
41
42
else :
42
43
# An eps is subtracted from the tilt to clip the far end of the camera
43
- y_max = params .projected_grid_params .f * np .tan (np .pi / 2 - params .projected_grid_params .tilt - eps )
44
+ y_max = params .projected_grid_params .f * \
45
+ np .tan (np .pi / 2 - params .projected_grid_params .tilt - eps )
44
46
45
47
params .bound_min = [x_min , y_min , params .bound_min [2 ]]
46
48
params .bound_max = [x_max , y_max , params .bound_max [2 ]]
@@ -55,23 +57,24 @@ def sample_egocentric_waypoints(self, vf=0.):
55
57
wf_n11 = np .zeros_like (wx_n11 )
56
58
# Project the (x, y, theta) points back in the world coordinates.
57
59
return self .generate_worldframe_waypoints_from_imageframe_waypoints (wx_n11 , wy_n11 , wtheta_n11 , vf_n11 , wf_n11 )
58
-
60
+
59
61
def generate_worldframe_waypoints_from_imageframe_waypoints (self , wx_n11 , wy_n11 , wtheta_n11 ,
60
62
vf_n11 = None , wf_n11 = None ):
61
63
"""
62
64
Project the (x, y, theta) waypoints in the image space back in the world coordinates. In the world frame x
63
65
correspond to Z (the depth) and y corresponds to the x direction in the image plane. The theta in the image
64
66
plane is measured positively anti-clockwise from the x-axis.
65
67
"""
66
- X_n1 , _ , Z_n1 = self .project_image_space_points_to_ground (np .hstack ([wx_n11 [:, :, 0 ], wy_n11 [:, :, 0 ]]))
68
+ X_n1 , _ , Z_n1 = self .project_image_space_points_to_ground (
69
+ np .hstack ([wx_n11 [:, :, 0 ], wy_n11 [:, :, 0 ]]))
67
70
# Project coordinates for determining angle (take a vector of magnitude 1e-5 in the direction of angle)
68
71
X_plus_delta_n1 , _ , Z_plus_delta_n1 = self .project_image_space_points_to_ground (
69
- np .hstack ([wx_n11 [:, :, 0 ] + 1e-5 * np .cos (wtheta_n11 [:, :, 0 ]),
70
- wy_n11 [:, :, 0 ] + 1e-5 * np .sin (wtheta_n11 [:, :, 0 ])]))
72
+ np .hstack ([wx_n11 [:, :, 0 ] + 1e-5 * np .cos (wtheta_n11 [:, :, 0 ]),
73
+ wy_n11 [:, :, 0 ] + 1e-5 * np .sin (wtheta_n11 [:, :, 0 ])]))
71
74
return Z_n1 [:, :, np .newaxis ], X_n1 [:, :, np .newaxis ], \
72
- np .arctan2 (X_plus_delta_n1 - X_n1 , Z_plus_delta_n1 - Z_n1 )[:, :, np .newaxis ], \
73
- vf_n11 , wf_n11
74
-
75
+ np .arctan2 (X_plus_delta_n1 - X_n1 , Z_plus_delta_n1 - Z_n1 )[:, :, np .newaxis ], \
76
+ vf_n11 , wf_n11
77
+
75
78
def generate_imageframe_waypoints_from_worldframe_waypoints (self , wx_n11 , wy_n11 , wtheta_n11 ,
76
79
vf_n11 = None , wf_n11 = None ):
77
80
"""
@@ -81,24 +84,27 @@ def generate_imageframe_waypoints_from_worldframe_waypoints(self, wx_n11, wy_n11
81
84
"""
82
85
# Project points in the optical coordinates
83
86
n = wx_n11 .shape [0 ]
84
- XYZ_world_coordinates_n3 = np .hstack ([wy_n11 [:, :, 0 ], np .zeros ((n , 1 )), wx_n11 [:, :, 0 ]])
85
- XYZ_optical_coordinates_n3 = self .convert_world_coordinates_to_optical_coordinates (XYZ_world_coordinates_n3 )
86
-
87
+ XYZ_world_coordinates_n3 = np .hstack (
88
+ [wy_n11 [:, :, 0 ], np .zeros ((n , 1 )), wx_n11 [:, :, 0 ]])
89
+ XYZ_optical_coordinates_n3 = self .convert_world_coordinates_to_optical_coordinates (
90
+ XYZ_world_coordinates_n3 )
91
+
87
92
# Project points in the optical coordinates for theta transformation
88
93
XYZ_plus_delta_world_coordinates_n3 = np .hstack ([wy_n11 [:, :, 0 ] + 1e-5 * np .sin (wtheta_n11 [:, :, 0 ]),
89
94
np .zeros ((n , 1 )),
90
95
wx_n11 [:, :, 0 ] + 1e-5 * np .cos (wtheta_n11 [:, :, 0 ])])
91
96
XYZ_plus_delta_optical_coordinates_n3 = self .convert_world_coordinates_to_optical_coordinates (
92
97
XYZ_plus_delta_world_coordinates_n3 )
93
-
98
+
94
99
# Project optical coordinates into image space
95
- x_n1 , y_n1 = self .project_optical_coordinates_to_image_space (XYZ_optical_coordinates_n3 )
100
+ x_n1 , y_n1 = self .project_optical_coordinates_to_image_space (
101
+ XYZ_optical_coordinates_n3 )
96
102
x_plus_delta_n1 , y_plus_delta_n1 = self .project_optical_coordinates_to_image_space (
97
103
XYZ_plus_delta_optical_coordinates_n3 )
98
-
104
+
99
105
return x_n1 [:, :, np .newaxis ], y_n1 [:, :, np .newaxis ], \
100
- np .arctan2 (y_plus_delta_n1 - y_n1 , x_plus_delta_n1 - x_n1 )[:, :, np .newaxis ], \
101
- vf_n11 , wf_n11
106
+ np .arctan2 (y_plus_delta_n1 - y_n1 , x_plus_delta_n1 - x_n1 )[:, :, np .newaxis ], \
107
+ vf_n11 , wf_n11
102
108
103
109
def worldframe_waypoint_direction_indicator (self , wx_n11 , wy_n11 , wtheta_n11 , vf_n11 = None ,
104
110
wf_n11 = None ):
@@ -108,18 +114,22 @@ def worldframe_waypoint_direction_indicator(self, wx_n11, wy_n11, wtheta_n11, vf
108
114
-1 if "behind the camera" (Z coordinate negative).
109
115
"""
110
116
n = wx_n11 .shape [0 ]
111
- XYZ_world_coordinates_n3 = np .hstack ([wy_n11 [:, :, 0 ], np .zeros ((n , 1 )), wx_n11 [:, :, 0 ]])
112
- XYZ_optical_coordinates_n3 = self .convert_world_coordinates_to_optical_coordinates (XYZ_world_coordinates_n3 )
113
- return tf .sign (XYZ_optical_coordinates_n3 [:, 2 ])[:, None , None ]
117
+ XYZ_world_coordinates_n3 = np .hstack (
118
+ [wy_n11 [:, :, 0 ], np .zeros ((n , 1 )), wx_n11 [:, :, 0 ]])
119
+ XYZ_optical_coordinates_n3 = self .convert_world_coordinates_to_optical_coordinates (
120
+ XYZ_world_coordinates_n3 )
121
+ return np .sign (XYZ_optical_coordinates_n3 [:, 2 ])[:, None , None ]
114
122
115
123
def project_optical_coordinates_to_image_space (self , XYZ_n3 ):
116
124
"""
117
125
Project a series of coordinates from the optical frame to the image space.
118
126
"""
119
- x_n = - self .params .projected_grid_params .f * XYZ_n3 [:, 0 ] / XYZ_n3 [:, 2 ]
120
- y_n = - self .params .projected_grid_params .f * XYZ_n3 [:, 1 ] / XYZ_n3 [:, 2 ]
127
+ x_n = - self .params .projected_grid_params .f * \
128
+ XYZ_n3 [:, 0 ] / XYZ_n3 [:, 2 ]
129
+ y_n = - self .params .projected_grid_params .f * \
130
+ XYZ_n3 [:, 1 ] / XYZ_n3 [:, 2 ]
121
131
return x_n [:, np .newaxis ], y_n [:, np .newaxis ]
122
-
132
+
123
133
def project_image_space_points_to_ground (self , xy_n2 ):
124
134
"""
125
135
Project a series of points in the image space to the ground plane.
@@ -132,12 +142,14 @@ def project_image_space_points_to_ground(self, xy_n2):
132
142
tilt = self .params .projected_grid_params .tilt
133
143
h = self .params .projected_grid_params .h
134
144
n = xy_n2 .shape [0 ]
135
- deno_n1 = self .params .projected_grid_params .f * np .sin (tilt ) + xy_n2 [:, 1 :2 ] * np .cos (tilt )
136
- X_n1 = - 1. * xy_n2 [:, 0 :1 ] * h / deno_n1
145
+ deno_n1 = self .params .projected_grid_params .f * \
146
+ np .sin (tilt ) + xy_n2 [:, 1 :2 ] * np .cos (tilt )
147
+ X_n1 = - 1. * xy_n2 [:, 0 :1 ] * h / deno_n1
137
148
Y_n1 = np .zeros ((n , 1 ))
138
- Z_n1 = h * (self .params .projected_grid_params .f * np .cos (tilt ) - xy_n2 [:, 1 :2 ] * np .sin (tilt )) / deno_n1
149
+ Z_n1 = h * (self .params .projected_grid_params .f *
150
+ np .cos (tilt ) - xy_n2 [:, 1 :2 ] * np .sin (tilt )) / deno_n1
139
151
return X_n1 , Y_n1 , Z_n1
140
-
152
+
141
153
def convert_world_coordinates_to_optical_coordinates (self , xyz_n3 ):
142
154
"""
143
155
Convert a series of coordinates from the world frame to the optical frame (the one that is aligned with the
@@ -146,15 +158,15 @@ def convert_world_coordinates_to_optical_coordinates(self, xyz_n3):
146
158
# First translate the points and then rotate them.
147
159
xyz_n3 = xyz_n3 - self .T_world_optical
148
160
return xyz_n3 .dot (self .R_world_optical .transpose ())
149
-
161
+
150
162
def convert_optical_coordinates_to_world_coordinates (self , xyz_n3 ):
151
163
"""
152
164
Convert a series of coordinates from the optical frame to the world frame.
153
165
"""
154
166
# First rotate and then translate the points.
155
167
xyz_n3 = xyz_n3 .dot (self .R_optical_world .transpose ())
156
168
return xyz_n3 - self .T_optical_world
157
-
169
+
158
170
def compute_rotation_and_translation_transformations (self ):
159
171
"""
160
172
Compute the rotation and translation matrices from the world frame to the optical frame and vice-versa.
@@ -170,9 +182,11 @@ def compute_rotation_and_translation_transformations(self):
170
182
self .R_optical_world = np .array ([[1. , 0. , 0. ],
171
183
[0. , np .cos (tilt ), - np .sin (tilt )],
172
184
[0. , np .sin (tilt ), np .cos (tilt )]])
173
- self .T_world_optical = np .array ([0. , self .params .projected_grid_params .h , 0. ])
174
- self .T_optical_world = np .array ([0. , - self .params .projected_grid_params .h , 0. ])
175
-
185
+ self .T_world_optical = np .array (
186
+ [0. , self .params .projected_grid_params .h , 0. ])
187
+ self .T_optical_world = np .array (
188
+ [0. , - self .params .projected_grid_params .h , 0. ])
189
+
176
190
@property
177
191
def descriptor_string (self ):
178
192
"""Returns a unique string identifying
0 commit comments