Skip to content
This repository was archived by the owner on Oct 13, 2021. It is now read-only.

Commit db9a897

Browse files
committed
Kitti Viewer Web major change:
1. add Cookie for paths, we don't need to paste paths in every launch. 2. add Bird's eye view and image.
1 parent 5a6a5d0 commit db9a897

File tree

6 files changed

+439
-83
lines changed

6 files changed

+439
-83
lines changed

README.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,34 @@ Currently there is a problem that training and evaluating in docker is very slow
208208

209209
## Try Kitti Viewer Web
210210

211+
### Major step
212+
211213
1. run ```python ./kittiviewer/backend.py main --port=xxxx``` in your server/local.
212214

213215
2. run ```cd ./kittiviewer/frontend && python -m http.server``` to launch a local web server.
214216

215-
3. open your browser and enter http://127.0.0.1:8000.
217+
3. open your browser and enter your frontend url (e.g. http://127.0.0.1:8000, default]).
216218

217-
4. input backend (http://your_server:your_backend_port)
219+
4. input backend url (e.g. http://127.0.0.1:16666)
218220

219221
5. input root path, info path and det path (optional)
220222

221-
6. click load, loadDet (optional), then click plot.
223+
6. click load, loadDet (optional), input image index in center bottom of screen and press Enter.
224+
225+
### Inference step
226+
227+
Firstly the load button must be clicked and load successfully.
228+
229+
1. input checkpointPath and configPath.
230+
231+
2. click buildNet.
232+
233+
3. click inference.
222234

223235
![GuidePic](https://raw.githubusercontent.com/traveller59/second.pytorch/master/images/viewerweb.png)
224236

237+
238+
225239
## Try Kitti Viewer (Deprecated)
226240

227241
You should use kitti viewer based on pyqt and pyqtgraph to check data before training.

images/viewerweb.png

-15.1 KB
Loading

second/kittiviewer/backend.py

+53-5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self):
3636
self.kitti_infos = None
3737
self.image_idxes = None
3838
self.dt_annos = None
39+
self.inference_ctx = None
3940

4041

4142
BACKEND = SecondBackend()
@@ -67,7 +68,7 @@ def readinfo():
6768
if not info_path.exists():
6869
response["status"] = "error"
6970
response["message"] = "ERROR: info file not exist."
70-
print("ERROR: your info_path is incorrect.")
71+
print("ERROR: your root path is incorrect.")
7172
return response
7273
BACKEND.info_path = info_path
7374
with open(info_path, 'rb') as f:
@@ -78,7 +79,6 @@ def readinfo():
7879

7980
response = jsonify(results=[response])
8081
response.headers['Access-Control-Allow-Headers'] = '*'
81-
print("read {} kitti info successful!".format(len(kitti_infos)))
8282
return response
8383

8484
@app.route('/api/read_detection', methods=['POST'])
@@ -100,15 +100,14 @@ def read_detection():
100100
BACKEND.dt_annos = dt_annos
101101
response = jsonify(results=[response])
102102
response.headers['Access-Control-Allow-Headers'] = '*'
103-
print("read {} detection successful!".format(len(dt_annos)))
104103
return response
105104

106105

107106
@app.route('/api/get_pointcloud', methods=['POST'])
108107
def get_pointcloud():
109108
global BACKEND
110109
instance = request.json
111-
response = {}
110+
response = {"status": "normal"}
112111
if BACKEND.root_path is None:
113112
return error_response("root path is not set")
114113
if BACKEND.kitti_infos is None:
@@ -119,13 +118,17 @@ def get_pointcloud():
119118
rect = kitti_info['calib/R0_rect']
120119
P2 = kitti_info['calib/P2']
121120
Trv2c = kitti_info['calib/Tr_velo_to_cam']
121+
img_shape = kitti_info["img_shape"] # hw
122+
wh = np.array(img_shape[::-1])
123+
whwh = np.tile(wh, 2)
122124
if 'annos' in kitti_info:
123125
annos = kitti_info['annos']
124126
labels = annos['name']
125127
num_obj = len([n for n in annos['name'] if n != 'DontCare'])
126128
dims = annos['dimensions'][:num_obj]
127129
loc = annos['location'][:num_obj]
128130
rots = annos['rotation_y'][:num_obj]
131+
bbox = annos['bbox'][:num_obj] / whwh
129132
gt_boxes_camera = np.concatenate(
130133
[loc, dims, rots[..., np.newaxis]], axis=1)
131134
gt_boxes = box_np_ops.box_camera_to_lidar(
@@ -138,6 +141,8 @@ def get_pointcloud():
138141
response["locs"] = locs.tolist()
139142
response["dims"] = dims.tolist()
140143
response["rots"] = rots.tolist()
144+
response["bbox"] = bbox.tolist()
145+
141146
response["labels"] = labels[:num_obj].tolist()
142147

143148
v_path = str(Path(BACKEND.root_path) / kitti_info['velodyne_path'])
@@ -152,6 +157,7 @@ def get_pointcloud():
152157
num_obj = dims.shape[0]
153158
loc = dt_annos['location']
154159
rots = dt_annos['rotation_y']
160+
bbox = dt_annos['bbox'] / whwh
155161
labels = dt_annos['name']
156162

157163
dt_boxes_camera = np.concatenate(
@@ -166,13 +172,50 @@ def get_pointcloud():
166172
response["dt_dims"] = dims.tolist()
167173
response["dt_rots"] = rots.tolist()
168174
response["dt_labels"] = labels.tolist()
175+
response["dt_bbox"] = bbox.tolist()
169176
response["dt_scores"] = dt_annos["score"].tolist()
170177

171178
# if "score" in annos:
172179
# response["score"] = score.tolist()
173180
response = jsonify(results=[response])
174181
response.headers['Access-Control-Allow-Headers'] = '*'
175-
print("get point cloud successful, send response!")
182+
print("send response!")
183+
return response
184+
185+
@app.route('/api/get_image', methods=['POST'])
186+
def get_image():
187+
global BACKEND
188+
instance = request.json
189+
response = {"status": "normal"}
190+
if BACKEND.root_path is None:
191+
return error_response("root path is not set")
192+
if BACKEND.kitti_infos is None:
193+
return error_response("kitti info is not loaded")
194+
image_idx = instance["image_idx"]
195+
idx = BACKEND.image_idxes.index(image_idx)
196+
kitti_info = BACKEND.kitti_infos[idx]
197+
rect = kitti_info['calib/R0_rect']
198+
P2 = kitti_info['calib/P2']
199+
Trv2c = kitti_info['calib/Tr_velo_to_cam']
200+
if 'img_path' in kitti_info:
201+
img_path = kitti_info['img_path']
202+
if img_path != "":
203+
image_path = BACKEND.root_path / img_path
204+
print(image_path)
205+
with open(str(image_path), 'rb') as f:
206+
image_str = f.read()
207+
response["image_b64"] = base64.b64encode(image_str).decode("utf-8")
208+
response["image_b64"] = 'data:image/{};base64,'.format(image_path.suffix[1:]) + response["image_b64"]
209+
'''#
210+
response["rect"] = rect.tolist()
211+
response["P2"] = P2.tolist()
212+
response["Trv2c"] = Trv2c.tolist()
213+
response["L2CMat"] = ((rect @ Trv2c).T).tolist()
214+
response["C2LMat"] = np.linalg.inv((rect @ Trv2c).T).tolist()
215+
'''
216+
print("send an image with size {}!".format(len(response["image_b64"])))
217+
response = jsonify(results=[response])
218+
response.headers['Access-Control-Allow-Headers'] = '*'
176219
return response
177220

178221
@app.route('/api/build_network', methods=['POST'])
@@ -227,6 +270,9 @@ def inference_by_idx():
227270
points = box_np_ops.remove_outside_points(
228271
points, rect, Trv2c, P2, image_shape)
229272
print(points.shape[0])
273+
img_shape = kitti_info["img_shape"] # hw
274+
wh = np.array(img_shape[::-1])
275+
whwh = np.tile(wh, 2)
230276

231277
t = time.time()
232278
inputs = BACKEND.inference_ctx.get_inference_input_dict(
@@ -241,6 +287,7 @@ def inference_by_idx():
241287
loc = dt_annos['location']
242288
rots = dt_annos['rotation_y']
243289
labels = dt_annos['name']
290+
bbox = dt_annos['bbox'] / whwh
244291

245292
dt_boxes_camera = np.concatenate(
246293
[loc, dims, rots[..., np.newaxis]], axis=1)
@@ -255,6 +302,7 @@ def inference_by_idx():
255302
response["dt_rots"] = rots.tolist()
256303
response["dt_labels"] = labels.tolist()
257304
response["dt_scores"] = dt_annos["score"].tolist()
305+
response["dt_bbox"] = bbox.tolist()
258306

259307
response = jsonify(results=[response])
260308
response.headers['Access-Control-Allow-Headers'] = '*'

second/kittiviewer/frontend/css/main.css

+33
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
.btn {
2+
/*height: 100%;*/
3+
text-align: center;
4+
position: absolute;
5+
top: 90%;
6+
left: 40%;
7+
z-index: 2;
8+
font-size: 40pt;
9+
color:#bbb;
10+
}
11+
12+
.prev {
13+
left: 38%;
14+
/*transform: scale(3, 1);*/
15+
}
16+
.imgidx {
17+
background: transparent;
18+
width: 120px;
19+
height: 40px;
20+
font-size: 12pt;
21+
left: 47%;
22+
23+
border: 2px solid blue;
24+
border-radius: 5px;
25+
26+
}
27+
28+
.next {
29+
left: 58%;
30+
/*transform: scale(3, 1);*/
31+
}
32+
33+
134
.toasts {
235
position: fixed;
336
max-width: 100%;

0 commit comments

Comments
 (0)