Skip to content

Commit f549770

Browse files
committed
add scripts
1 parent 5773559 commit f549770

16 files changed

+1073
-0
lines changed

data splits/scenes_test.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2t7WUuJeko7
2+
5ZKStnWn8Zo
3+
ARNzJeq3xxb
4+
fzynW3qQPVF
5+
jtcxE69GiFV
6+
pa4otMbVnkk
7+
q9vSo1VnCiC
8+
rqfALeAoiTq
9+
UwV83HsGsw3
10+
wc2JMjhGNzB
11+
WYY7iVyf5p8
12+
YFuZgdQ5vWj
13+
yqstnuAEVhm
14+
YVUC4YcDtcY
15+
gxdoqLR6rwA
16+
gYvKGZ5eRqb
17+
RPmz2sHmrrY
18+
Vt2qJdWjCF2

data splits/scenes_train.txt

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
17DRP5sb8fy
2+
1LXtFkjw3qL
3+
1pXnuDYAj8r
4+
29hnd4uzFmX
5+
5LpN3gDmAk7
6+
5q7pvUzZiYa
7+
759xd9YjKW5
8+
7y3sRwLe3Va
9+
82sE5b5pLXE
10+
8WUmhLawc2A
11+
aayBHfsNo7d
12+
ac26ZMwG7aT
13+
B6ByNegPMKs
14+
b8cTxDM8gDG
15+
cV4RVeZvu5T
16+
D7N2EKCX4Sj
17+
e9zR4mvMWw7
18+
EDJbREhghzL
19+
GdvgFV5R1Z5
20+
gTV8FGcVJC9
21+
HxpKQynjfin
22+
i5noydFURQK
23+
JeFG25nYj2p
24+
JF19kD82Mey
25+
jh4fc5c5qoQ
26+
kEZ7cmS4wCh
27+
mJXqzFtmKg4
28+
p5wJjkQkbXX
29+
Pm6F8kyY3z2
30+
pRbA3pwrgk9
31+
PuKPg4mmafe
32+
PX4nDJXEHrG
33+
qoiz87JEwZ2
34+
rPc6DW4iMge
35+
s8pcmisQ38h
36+
S9hNv5qa7GM
37+
sKLMLpTHeUy
38+
SN83YJsR3w2
39+
sT4fr6TAbpF
40+
ULsKaCPVFJR
41+
uNb9QFRL6hY
42+
Uxmj2M2itWa
43+
V2XKFyX4ASd
44+
VFuaQ6m2Qom
45+
VVfe2KiqLaN
46+
Vvot9Ly1tCj
47+
vyrNrziPKCB
48+
VzqfbhrpDEA
49+
XcA2TqTSSAj
50+
2n8kARJN3HM
51+
D7G3Y4RVNrH
52+
dhjEzFoUFzH
53+
E9uDoFAP3SH
54+
gZ6f7yhEvPG
55+
JmbYfDe2QKZ
56+
r1Q1Z4BcV1o
57+
r47D5H71a5s
58+
ur6pFq6Qu1A
59+
VLzqgDo317F
60+
YmJkqBEsHnH
61+
ZMojNkEp431

data splits/scenes_val.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2azQ1b91cZZ
2+
8194nk5LbLH
3+
EU6Fwq7SyZv
4+
oLBMNvg9in8
5+
QUCTc6BB5sX
6+
TbHJrupSAjP
7+
X7HyMhZNoso
8+
pLe4wQe7qrG
9+
x8F5xyUWy9e
10+
Z6MFQCViBuw
11+
zsNo4HB9uLZ

dataset/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .dataloader import *

dataset/dataloader.py

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import os
2+
import sys
3+
import torch
4+
from torch.utils.data.dataset import Dataset
5+
from torch.utils.data import DataLoader
6+
import importers
7+
import warnings
8+
from PIL import Image
9+
import utils
10+
11+
class DataLoaderParams:
12+
def __init__(self,
13+
root_path,
14+
trajectories_dir,
15+
data_split,
16+
drone_list,
17+
view_list,
18+
frame_list,
19+
types_list,
20+
transform):
21+
22+
self.root_path = root_path
23+
self.trajectories_dir = trajectories_dir
24+
self.data_split = data_split
25+
self.drone_list = drone_list
26+
self.view_list = view_list
27+
self.frame_list = frame_list
28+
self.types_list = types_list
29+
self.transform = transform
30+
31+
class DataLoad(Dataset):
32+
def __init__(self,params):
33+
super(DataLoad,self).__init__()
34+
self.params = params
35+
root_path = self.params.root_path
36+
trajectories_dir = self.params.trajectories_dir
37+
data_split = self.params.data_split
38+
39+
self.data = {}
40+
41+
buildings = self.get_splits(data_split)
42+
43+
for drone in os.listdir(root_path):
44+
#ignore not included drone models
45+
if drone not in self.params.drone_list:
46+
continue
47+
root_path_ = os.path.join(root_path,drone)
48+
for view in os.listdir(root_path_):
49+
view_path = os.path.join(root_path_,view)
50+
#get included types
51+
for type_ in os.listdir(view_path):
52+
if type_ not in self.params.types_list:
53+
continue
54+
#get images for each building
55+
for building in buildings:
56+
img_path = os.path.join(view_path,type_,building)
57+
for img in os.listdir(img_path):
58+
if (len(img.split("_")) <= 6):
59+
row, date , frame , __ , view , _ = img.split("_")
60+
else:
61+
row, date , frame , __ ,_, view , _ = img.split("_")
62+
#get only included view
63+
if view not in self.params.view_list:
64+
continue
65+
#ignore not listed frame
66+
if int(frame) not in self.params.frame_list:
67+
continue
68+
#NOTE:set the path to the extrinsics file
69+
full_img_name = os.path.join(img_path,img)
70+
#set a unique name for each row
71+
unique_name = building + "_" + str(row) + "_" + str(date)
72+
if unique_name not in self.data:
73+
self.data[unique_name] = {}
74+
75+
if view not in self.data[unique_name]:
76+
self.data[unique_name][view] = {}
77+
78+
if frame not in self.data[unique_name][view]:
79+
self.data[unique_name][view][frame] = {}
80+
81+
self.data[unique_name][view][frame][type_] = full_img_name
82+
def __len__(self):
83+
return len(self.data)
84+
85+
def __getitem__(self,idx):
86+
#get an entry
87+
key = list(self.data.keys())[idx]
88+
datum = self.data[key]
89+
datum_out = {}
90+
for view in self.params.view_list:
91+
datum_view = {}
92+
for frame in self.params.frame_list:
93+
frame_dict = {}
94+
for type_ in self.params.types_list:
95+
if type_ == "colour":
96+
value = importers.image.load_image(datum[view][str(frame)][type_])
97+
#apply transform
98+
if self.params.transform is not None:
99+
value = self.params.transform(value)
100+
elif type_ == "silhouette" and view == "exocentric":
101+
value = importers.image.load_image(datum[view][str(frame)][type_])
102+
elif type_ == "colour" or type_ == "silhouette":
103+
continue
104+
elif type_ == "depth":
105+
value = importers.image.load_depth(datum[view][str(frame)][type_])
106+
elif type_ == "normal":
107+
value = importers.image.load_depth(datum[view][str(frame)][type_])
108+
else:
109+
vsalue = importers.image.load_image(datum[view][str(frame)][type_])
110+
frame_dict.update({str(type_) : value.squeeze(0)})
111+
#load pose for each frame
112+
if view == "exocentric":
113+
pose , pose_inv = importers.load_pose(key,self.params.trajectories_dir,frame)
114+
frame_dict.update({"pose":pose,"pose_inv" : pose_inv, 'key':key})
115+
else:
116+
#NOTE:get source to target pose (t0,t1)
117+
if int(frame) == 1:
118+
#set source to 0
119+
source_ = 0
120+
else:
121+
#source is 1
122+
source_ = 1
123+
ego_pose = importers.load_egoPose(key,self.params.trajectories_dir,source_,int(frame))
124+
frame_dict.update({'key':key , 'source_to_target' : ego_pose})
125+
datum_view.update({
126+
frame:frame_dict
127+
})
128+
datum_out.update({
129+
view:datum_view
130+
})
131+
return datum_out
132+
133+
def get_data(self):
134+
return self.data
135+
136+
def get_splits(self,split):
137+
138+
if split == "train":
139+
txt_path = os.path.join(os.getcwd(),"data splits","scenes_train.txt")
140+
141+
elif split == "test":
142+
txt_path = os.path.join(os.getcwd(),"data splits","scenes_test.txt")
143+
144+
elif split == "val":
145+
txt_path = os.path.join(os.getcwd(),"data splits","scenes_val.txt")
146+
147+
with open(txt_path,'r') as txt_file:
148+
splits = [line.strip() for line in txt_file]
149+
150+
return splits

importers/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .extrinsics import *
2+
from .intrinsics import *
3+
from .image import *

importers/extrinsics.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import numpy as np
2+
import torch
3+
import pandas as pd
4+
import os
5+
from utils import geometry
6+
7+
8+
def qmul(q, r):
9+
"""
10+
Multiply quaternion(s) q with quaternion(s) r.
11+
Expects two equally-sized tensors of shape (*, 4), where * denotes any number of dimensions.
12+
Returns q*r as a tensor of shape (*, 4).
13+
"""
14+
assert q.shape[-1] == 4
15+
assert r.shape[-1] == 4
16+
17+
original_shape = q.shape
18+
19+
# Compute outer product
20+
terms = torch.bmm(r.view(-1, 4, 1), q.view(-1, 1, 4))
21+
22+
w = terms[:, 0, 0] - terms[:, 1, 1] - terms[:, 2, 2] - terms[:, 3, 3]
23+
x = terms[:, 0, 1] + terms[:, 1, 0] - terms[:, 2, 3] + terms[:, 3, 2]
24+
y = terms[:, 0, 2] + terms[:, 1, 3] + terms[:, 2, 0] - terms[:, 3, 1]
25+
z = terms[:, 0, 3] - terms[:, 1, 2] + terms[:, 2, 1] + terms[:, 3, 0]
26+
return torch.stack((w, x, y, z), dim=1).view(original_shape)
27+
28+
29+
def load_extrinsics(filename, data_type=torch.float32):
30+
data = np.loadtxt(filename)
31+
pose = np.zeros([4, 4])
32+
pose[3, 3] = 1
33+
pose[:3, :3] = data[:3, :3]
34+
pose[:3, 3] = data[3, :]
35+
extrinsics = torch.tensor(pose, dtype=data_type)
36+
return extrinsics , extrinsics.inverse()
37+
38+
def load_pose(key,trajectories_dir,frame):
39+
building , row , date = key.split("_")
40+
i = int(row)
41+
csv_file = os.listdir(os.path.join(trajectories_dir,building,date))
42+
for file in csv_file:
43+
if "blender" in file:
44+
csv_name = file
45+
46+
csv = pd.read_csv(os.path.join(trajectories_dir,building,date,csv_name),sep='\t',decimal='.')
47+
48+
if frame == 0:
49+
Rd = np.array([csv['Orientation(x)_t1'][i],csv['Orientation(y)_t1'][i],csv['Orientation(z)_t1'][i],csv['Orientation(w)_t1'][i]])
50+
Td = np.array([csv['Position(x)_t1'][i],csv['Position(y)_t1'][i],csv['Position(z)_t1'][i]])
51+
else:
52+
Rd = np.array([csv['Orientation(x)_t2'][i],csv['Orientation(y)_t2'][i],csv['Orientation(z)_t2'][i],csv['Orientation(w)_t2'][i]])
53+
Td = np.array([csv['Position(x)_t2'][i],csv['Position(y)_t2'][i],csv['Position(z)_t2'][i]])
54+
#read camera's pose
55+
Rc = np.array([csv['PilotRot(x)'][i],csv['PilotRot(y)'][i],csv['PilotRot(z)'][i],csv['PilotRot(w)'][i]])
56+
Tc = np.array([ csv['Pilot(x)'][i],csv['Pilot(y)'][i],csv['Pilot(z)'][i]])
57+
58+
#get drone matrix in world space
59+
Pdw = geometry.objectMatrix(Rd,Td)
60+
#get camera matrix in world space
61+
Pcw = geometry.objectMatrix(Rc,Tc)
62+
63+
PdroneToCamera = geometry.getRelativeMatrix(Pdw[:3,:3],Pcw[:3,:3],Pdw[:3,3],Pcw[:3,3])
64+
65+
66+
return PdroneToCamera , PdroneToCamera.inverse()
67+
68+
def load_egoPose(key , trajectories_dir ,target_,source_):
69+
building , row , date = key.split("_")
70+
i = int(row)
71+
csv_file = os.listdir(os.path.join(trajectories_dir,building,date))
72+
for file in csv_file:
73+
if "blender" in file:
74+
csv_name = file
75+
76+
csv = pd.read_csv(os.path.join(trajectories_dir,building,date,csv_name),sep='\t',decimal='.')
77+
#read source pose
78+
if target_ == 1:
79+
Rsource = np.array([csv['Orientation(x)_t1'][i],csv['Orientation(y)_t1'][i],csv['Orientation(z)_t1'][i],csv['Orientation(w)_t1'][i]])
80+
Tsource = np.array([csv['Position(x)_t1'][i],csv['Position(y)_t1'][i],csv['Position(z)_t1'][i]])
81+
#read target pose
82+
Rtarget = np.array([csv['Orientation(x)_t2'][i],csv['Orientation(y)_t2'][i],csv['Orientation(z)_t2'][i],csv['Orientation(w)_t2'][i]])
83+
Ttarget = np.array([csv['Position(x)_t2'][i],csv['Position(y)_t2'][i],csv['Position(z)_t2'][i]])
84+
else:
85+
Rtarget = np.array([csv['Orientation(x)_t1'][i],csv['Orientation(y)_t1'][i],csv['Orientation(z)_t1'][i],csv['Orientation(w)_t1'][i]])
86+
Ttarget = np.array([csv['Position(x)_t1'][i],csv['Position(y)_t1'][i],csv['Position(z)_t1'][i]])
87+
#read source pose
88+
Tsource = np.array([csv['Position(x)_t2'][i],csv['Position(y)_t2'][i],csv['Position(z)_t2'][i]])
89+
Rsource = np.array([csv['Orientation(x)_t2'][i],csv['Orientation(y)_t2'][i],csv['Orientation(z)_t2'][i],csv['Orientation(w)_t2'][i]])
90+
91+
#get source pose matrix in world space
92+
source_extrinsics = geometry.objectMatrix(Rsource,Tsource)
93+
#get target pose matrix in world space
94+
target_extrinsics = geometry.objectMatrix(Rtarget,Ttarget)
95+
96+
source_to_target_pose = target_extrinsics.inverse() @ source_extrinsics
97+
98+
return source_to_target_pose

importers/image.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import cv2
2+
import torch
3+
import numpy
4+
5+
def load_image(filename, data_type=torch.float32):
6+
color_img = numpy.array(cv2.imread(filename, cv2.IMREAD_ANYCOLOR))
7+
h, w, c = color_img.shape
8+
color_data = color_img.astype(numpy.float32).transpose(2, 0, 1)
9+
return torch.from_numpy(
10+
color_data.reshape(1, c, h, w)
11+
).type(data_type) / 255.0
12+
13+
def load_depth(filename, data_type=torch.float32, scale=1.0):
14+
depth_img = numpy.array(cv2.imread(filename, cv2.IMREAD_ANYDEPTH))
15+
h, w = depth_img.shape
16+
depth_data = depth_img.astype(numpy.float32) * scale
17+
return torch.from_numpy(
18+
depth_data.reshape(1, 1, h, w)
19+
).type(data_type)
20+
21+
def crop_depth(filename, data_type=torch.float32, scale=0.001):
22+
depth_img = numpy.array(cv2.imread(filename, cv2.IMREAD_ANYDEPTH))
23+
center_cropped_depth_img = depth_img[60:420, 0:640]
24+
h, w = center_cropped_depth_img.shape
25+
depth_data = center_cropped_depth_img.astype(numpy.float32) * scale
26+
return torch.from_numpy(
27+
depth_data.reshape(1, 1, h, w)
28+
).type(data_type)
29+
30+
def load_normal(filename, data_type=torch.float32):
31+
normal_img = numpy.array(cv2.imread(filename, cv2.IMREAD_UNCHANGED)).transpose(2, 0, 1)
32+
c, h, w = normal_img.shape
33+
return torch.from_numpy(normal_img).reshape(1,c, h, w).type(data_type)

0 commit comments

Comments
 (0)