Mercurial > hg > nsaunier > traffic-intelligence
comparison trafficintelligence/storage.py @ 1255:c0fe55a6b82f
added support for LUMPI 3D data format
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Wed, 03 Apr 2024 12:30:36 -0400 |
| parents | a477ad82ab66 |
| children | 56d0195d043e |
comparison
equal
deleted
inserted
replaced
| 1254:a477ad82ab66 | 1255:c0fe55a6b82f |
|---|---|
| 1269 inv_Tr = zeros_like(Tr) # 3x4 | 1269 inv_Tr = zeros_like(Tr) # 3x4 |
| 1270 inv_Tr[0:3, 0:3] = transpose(Tr[0:3, 0:3]) | 1270 inv_Tr[0:3, 0:3] = transpose(Tr[0:3, 0:3]) |
| 1271 inv_Tr[0:3, 3] = dot(-transpose(Tr[0:3, 0:3]), Tr[0:3, 3]) | 1271 inv_Tr[0:3, 3] = dot(-transpose(Tr[0:3, 0:3]), Tr[0:3, 3]) |
| 1272 return inv_Tr | 1272 return inv_Tr |
| 1273 | 1273 |
| 1274 def compute3Dbox(anno_list): | |
| 1275 #### LiDAR coordinate, rotate with y | |
| 1276 '''.DS_Store | |
| 1277 ^ z | |
| 1278 | | |
| 1279 | | |
| 1280 | | |
| 1281 . - - - - - - - > x | |
| 1282 / | |
| 1283 / | |
| 1284 / | |
| 1285 v y | |
| 1286 | |
| 1287 ''' | |
| 1288 from pykitti.utils import rotz | |
| 1289 | |
| 1290 R = rotz(anno_list['heading_3d']) | |
| 1291 l = anno_list['l_3d'] | |
| 1292 w = anno_list['w_3d'] | |
| 1293 h = anno_list['h_3d'] | |
| 1294 | |
| 1295 x_3d = anno_list['x_3d'] | |
| 1296 y_3d = anno_list['y_3d'] | |
| 1297 z_3d = anno_list['z_3d'] | |
| 1298 | |
| 1299 # # 3d bounding box corners x,y,z as center of the 3d bbox | |
| 1300 # # 0 1 2 3 4 5 6 7 | |
| 1301 x_corners = [l/2, l/2, -l/2, -l/2, l/2, l/2, -l/2, -l/2] | |
| 1302 y_corners = [w/2, -w/2, -w/2, w/2, w/2, -w/2, -w/2, w/2] | |
| 1303 z_corners = [h/2, h/2, h/2, h/2, -h/2, -h/2, -h/2, -h/2] | |
| 1304 | |
| 1305 # 3d bounding box corners x,y,z as center of the bottom surface of the 3d bbox, | |
| 1306 # the difference occurs at z_corners, as it rotates with z_corners. | |
| 1307 # x_corners = [l/2, l/2, -l/2, -l/2, l/2, l/2, -l/2, -l/2] | |
| 1308 # y_corners = [w/2, -w/2, -w/2, w/2, w/2, -w/2, -w/2, w/2] | |
| 1309 # z_corners = [h, h, h, h, 0, 0, 0, 0] | |
| 1310 corners_3d = dot(R, vstack([x_corners, y_corners, z_corners])) | |
| 1311 # add the center | |
| 1312 corners_3d[0, :] = corners_3d[0, :] + x_3d | |
| 1313 corners_3d[1, :] = corners_3d[1, :] + y_3d | |
| 1314 corners_3d[2, :] = corners_3d[2, :] + z_3d | |
| 1315 | |
| 1316 return transpose(corners_3d) | |
| 1317 | |
| 1274 def loadKITTICalibration(filename): | 1318 def loadKITTICalibration(filename): |
| 1275 '''Loads KITTI calibration data''' | 1319 '''Loads KITTI calibration data''' |
| 1276 calib = {} | 1320 calib = {} |
| 1277 with open(filename, 'r') as f: | 1321 with open(filename, 'r') as f: |
| 1278 for l in f: | 1322 for l in f: |
| 1302 return calib | 1346 return calib |
| 1303 | 1347 |
| 1304 # from https://github.com/utiasSTARS/pykitti/blob/master/pykitti/utils.py | 1348 # from https://github.com/utiasSTARS/pykitti/blob/master/pykitti/utils.py |
| 1305 | 1349 |
| 1306 | 1350 |
| 1307 def loadTrajectoriesFromKITTI(filename, kittiCalibration, oxts, resultFile = False): | 1351 def loadTrajectoriesFromKITTI(filename, kittiCalibration = None, oxts = None, resultFile = False): |
| 1308 '''Reads data from KITTI ground truth or output from an object detection and tracking method | 1352 '''Reads data from KITTI ground truth or output from an object detection and tracking method |
| 1309 | 1353 |
| 1310 kittiCalibration is obtained from loading training/testing calibration file for each sequence 00XX.txt | 1354 kittiCalibration is obtained from loading training/testing calibration file for each sequence 00XX.txt |
| 1311 oxts is obtained using utils.load_oxts_packets_and_poses(['./training/oxts/0001.txt']) from pykitti | 1355 oxts is obtained using utils.load_oxts_packets_and_poses(['./training/oxts/0001.txt']) from pykitti |
| 1312 | 1356 |
| 1313 Ref: https://github.com/pratikac/kitti/blob/master/readme.tracking.txt''' | 1357 Ref: https://github.com/pratikac/kitti/blob/master/readme.tracking.txt''' |
| 1314 from pykitti.utils import roty | 1358 from pykitti.utils import roty |
| 1315 from trafficintelligence.cvutils import cartesian2Homogeneous | 1359 from trafficintelligence.cvutils import cartesian2Homogeneous |
| 1316 | 1360 |
| 1317 invR0 = linalg.inv(reshape(kittiCalibration['R_rect'], (3, 3))) | 1361 if kittiCalibration is not None: |
| 1318 transCam2Velo = transpose(kittiCalibration['Tr_cam_velo']) | 1362 invR0 = linalg.inv(reshape(kittiCalibration['R_rect'], (3, 3))) |
| 1363 transCam2Velo = transpose(kittiCalibration['Tr_cam_velo']) | |
| 1319 | 1364 |
| 1320 header = ['frame', # 0, 1, ..., n | 1365 header = ['frame', # 0, 1, ..., n |
| 1321 'trackingid', # -1, 0 , 1, ..., k | 1366 'trackingid', # -1, 0 , 1, ..., k |
| 1322 'usertype', # 'Car', 'Pedestrian', ... | 1367 'usertype', # 'Car', 'Pedestrian', ... |
| 1323 'truncation', # truncated pixel ratio [0..1] | 1368 'truncation', # truncated pixel ratio [0..1] |
| 1351 instants = set(interval).difference(tmp.frame) | 1396 instants = set(interval).difference(tmp.frame) |
| 1352 missing = concat([tmp[header[10:]], DataFrame([[t]+[NaN]*(len(header)-10) for t in instants], columns = ['frame']+header[10:])], ignore_index=True).sort_values('frame') | 1397 missing = concat([tmp[header[10:]], DataFrame([[t]+[NaN]*(len(header)-10) for t in instants], columns = ['frame']+header[10:])], ignore_index=True).sort_values('frame') |
| 1353 tmp = missing.interpolate() | 1398 tmp = missing.interpolate() |
| 1354 featureTrajectories = [moving.Trajectory() for i in range(4)] | 1399 featureTrajectories = [moving.Trajectory() for i in range(4)] |
| 1355 for i, r in tmp.iterrows(): | 1400 for i, r in tmp.iterrows(): |
| 1356 _, Tr_imu_to_world = oxts[r.frame] | 1401 if kittiCalibration is not None: |
| 1357 # transfer_matrix = {'P2': reshape(kittiCalibration['P2'], (3, 4)), | 1402 _, Tr_imu_to_world = oxts[r.frame] |
| 1358 # 'R_rect': kittiCalibration['R_rect'], | 1403 # transfer_matrix = {'P2': reshape(kittiCalibration['P2'], (3, 4)), |
| 1359 # 'Tr_cam_to_velo': kittiCalibration['Tr_cam_velo'], | 1404 # 'R_rect': kittiCalibration['R_rect'], |
| 1360 # # transfer_matrix['Tr_velo_to_cam'] = kittiCalibration['Tr_velo_to_cam'] | 1405 # 'Tr_cam_to_velo': kittiCalibration['Tr_cam_velo'], |
| 1361 # 'Tr_velo_to_imu': kittiCalibration['Tr_velo_imu'], | 1406 # # transfer_matrix['Tr_velo_to_cam'] = kittiCalibration['Tr_velo_to_cam'] |
| 1362 # # transfer_matrix['Tr_imu_to_velo'] = kittiCalibration['Tr_imu_to_velo'] | 1407 # 'Tr_velo_to_imu': kittiCalibration['Tr_velo_imu'], |
| 1363 # 'Tr_imu_to_world': Tr_imu2w} | 1408 # # transfer_matrix['Tr_imu_to_velo'] = kittiCalibration['Tr_imu_to_velo'] |
| 1364 # 3D object | 1409 # 'Tr_imu_to_world': Tr_imu2w} |
| 1365 # compute rotational matrix around yaw axis | 1410 # 3D object |
| 1366 R = roty(r.ry) | 1411 # compute rotational matrix around yaw axis |
| 1367 | 1412 R = roty(r.ry) |
| 1413 | |
| 1414 # 3d bounding box corners | |
| 1415 x_corners = [r.l / 2, r.l / 2, -r.l / 2, -r.l / 2, r.l / 2, r.l / 2, -r.l / 2, -r.l / 2] | |
| 1416 y_corners = [0, 0, 0, 0, -r.h, -r.h, -r.h, -r.h] | |
| 1417 z_corners = [r.w / 2, -r.w / 2, -r.w / 2, r.w / 2, r.w / 2, -r.w / 2, -r.w / 2, r.w / 2] | |
| 1418 # rotate and translate 3d bounding box | |
| 1419 corners3d = dot(R, vstack([x_corners, y_corners, z_corners])) | |
| 1420 corners3d[0, :] = corners3d[0, :] + r.x#obj.t[0] | |
| 1421 corners3d[1, :] = corners3d[1, :] + r.y#obj.t[1] | |
| 1422 corners3d[2, :] = corners3d[2, :] + r.z#obj.t[2] | |
| 1423 # corners3d = transpose(corners3d) | |
| 1424 # box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d) | |
| 1425 refCorners = transpose(dot(invR0, corners3d)) # 8x3 avoid double transpose np.transpose(pts_3d_rect))) in pts_3d_ref = self.project_rect_to_ref(pts_3d_rect) | |
| 1426 homRefCorners = cartesian2Homogeneous(refCorners) | |
| 1427 veloCorners = dot(homRefCorners, transCam2Velo) | |
| 1428 # self.project_ref_to_velo(pts_3d_ref) | |
| 1429 # boxes3d_world_single, flag_imu, flag_world = calib_function.project_velo_to_world(bboxes_3d_velo=boxes3d_velo_single, Tr_matrix=transfer_matrix) | |
| 1430 #Tr_velo_to_imu = transfer_matrix['Tr_velo_to_imu'] | |
| 1431 #Tr_imu_to_world = transfer_matrix['Tr_imu_to_world'] | |
| 1432 homVeloCorners = cartesian2Homogeneous(veloCorners) | |
| 1433 imuCorners = dot(kittiCalibration['Tr_velo_imu'], homVeloCorners.T).T # 8x3 | |
| 1434 | |
| 1435 homImuCorners = cartesian2Homogeneous(imuCorners) | |
| 1436 worldCorners = dot(Tr_imu_to_world, homImuCorners.T).T # 8x3 | |
| 1437 else: #LUMPI format | |
| 1438 anno_list_temp = {} | |
| 1439 anno_list_temp['x_2d'] = r.xmin | |
| 1440 anno_list_temp['y_2d'] = r.ymin | |
| 1441 anno_list_temp['l_3d'] = r.l | |
| 1442 anno_list_temp['w_3d'] = r.w | |
| 1443 anno_list_temp['h_3d'] = r.h | |
| 1444 anno_list_temp['x_3d'] = r.x | |
| 1445 anno_list_temp['y_3d'] = r.y | |
| 1446 anno_list_temp['z_3d'] = r.z | |
| 1447 anno_list_temp['heading_3d'] = r.ry | |
| 1448 worldCorners = compute3Dbox(anno_list_temp) | |
| 1449 # take first 4 lines of corners, x,y,_ # x0, y0, _ = boxes3d[0] | |
| 1450 xCoords = worldCorners[:4,0] | |
| 1451 yCoords = worldCorners[:4,1] | |
| 1452 t.addPositionXY(xCoords.mean(), yCoords.mean()) | |
| 1453 for i in range(4): | |
| 1454 featureTrajectories[i].addPositionXY(xCoords[i], yCoords[i]) | |
| 1455 # check https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga1019495a2c8d1743ed5cc23fa0daff8c | |
| 1456 if interval.length()>1: | |
| 1457 objects.append(moving.MovingObject(num = objNum, timeInterval = interval, positions = t, velocities = t.differentiate(True), userType = userType, features = [moving.MovingObject(num = featureNum+i, timeInterval = copy(interval), positions = featureTrajectories[i], velocities = featureTrajectories[i].differentiate(True)) for i in range(4)])) | |
| 1458 featureNum += 4 | |
| 1459 | |
| 1460 # ego vehicle | |
| 1461 if oxts is not None: | |
| 1462 t = moving.Trajectory() | |
| 1463 featureTrajectories = [moving.Trajectory() for i in range(4)] | |
| 1464 interval = moving.TimeInterval(0, len(oxts)-1)#int(data.frame.min()), int(data.frame.max())) | |
| 1465 R = roty(pi/2) | |
| 1466 #for frame in interval: | |
| 1467 for _, Tr_imu_to_world in oxts: | |
| 1468 l = 4.5 # m | |
| 1469 w = 1.8 # m | |
| 1470 h = 0. | |
| 1368 # 3d bounding box corners | 1471 # 3d bounding box corners |
| 1369 x_corners = [r.l / 2, r.l / 2, -r.l / 2, -r.l / 2, r.l / 2, r.l / 2, -r.l / 2, -r.l / 2] | 1472 x_corners = [l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2] |
| 1370 y_corners = [0, 0, 0, 0, -r.h, -r.h, -r.h, -r.h] | 1473 y_corners = [0, 0, 0, 0, -h, -h, -h, -h] |
| 1371 z_corners = [r.w / 2, -r.w / 2, -r.w / 2, r.w / 2, r.w / 2, -r.w / 2, -r.w / 2, r.w / 2] | 1474 z_corners = [w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2] |
| 1372 # rotate and translate 3d bounding box | 1475 # rotate and translate 3d bounding box |
| 1373 corners3d = dot(R, vstack([x_corners, y_corners, z_corners])) | 1476 corners3d = dot(R, vstack([x_corners, y_corners, z_corners])) |
| 1374 corners3d[0, :] = corners3d[0, :] + r.x#obj.t[0] | 1477 corners3d[0, :] = corners3d[0, :] |
| 1375 corners3d[1, :] = corners3d[1, :] + r.y#obj.t[1] | 1478 corners3d[1, :] = corners3d[1, :] |
| 1376 corners3d[2, :] = corners3d[2, :] + r.z#obj.t[2] | 1479 corners3d[2, :] = corners3d[2, :] |
| 1377 # corners3d = transpose(corners3d) | |
| 1378 # box3d_pts_3d_velo = calib.project_rect_to_velo(box3d_pts_3d) | |
| 1379 refCorners = transpose(dot(invR0, corners3d)) # 8x3 avoid double transpose np.transpose(pts_3d_rect))) in pts_3d_ref = self.project_rect_to_ref(pts_3d_rect) | 1480 refCorners = transpose(dot(invR0, corners3d)) # 8x3 avoid double transpose np.transpose(pts_3d_rect))) in pts_3d_ref = self.project_rect_to_ref(pts_3d_rect) |
| 1380 homRefCorners = cartesian2Homogeneous(refCorners) | 1481 homRefCorners = cartesian2Homogeneous(refCorners) |
| 1381 veloCorners = dot(homRefCorners, transCam2Velo) | 1482 veloCorners = dot(homRefCorners, transCam2Velo) |
| 1382 # self.project_ref_to_velo(pts_3d_ref) | |
| 1383 # boxes3d_world_single, flag_imu, flag_world = calib_function.project_velo_to_world(bboxes_3d_velo=boxes3d_velo_single, Tr_matrix=transfer_matrix) | |
| 1384 #Tr_velo_to_imu = transfer_matrix['Tr_velo_to_imu'] | |
| 1385 #Tr_imu_to_world = transfer_matrix['Tr_imu_to_world'] | |
| 1386 homVeloCorners = cartesian2Homogeneous(veloCorners) | 1483 homVeloCorners = cartesian2Homogeneous(veloCorners) |
| 1387 imuCorners = dot(kittiCalibration['Tr_velo_imu'], homVeloCorners.T).T # 8x3 | 1484 imuCorners = dot(kittiCalibration['Tr_velo_imu'], homVeloCorners.T).T # 8x3 |
| 1388 | 1485 |
| 1389 homImuCorners = cartesian2Homogeneous(imuCorners) | 1486 homImuCorners = cartesian2Homogeneous(imuCorners) |
| 1390 worldCorners = dot(Tr_imu_to_world, homImuCorners.T).T # 8x3 | 1487 worldCorners = dot(Tr_imu_to_world, homImuCorners.T).T # 8x3 |
| 1391 | 1488 |
| 1392 # take first 4 lines of corners, x,y,_ # x0, y0, _ = boxes3d[0] | 1489 # take first 4 lines of corners, x,y,_ # x0, y0, _ = boxes3d[0] |
| 1393 xCoords = worldCorners[:4,0] | 1490 xCoords = worldCorners[:4,0] |
| 1394 yCoords = worldCorners[:4,1] | 1491 yCoords = worldCorners[:4,1] |
| 1395 t.addPositionXY(xCoords.mean(), yCoords.mean()) | 1492 t.addPositionXY(xCoords.mean(), yCoords.mean()) |
| 1396 for i in range(4): | 1493 for i in range(4): |
| 1397 featureTrajectories[i].addPositionXY(xCoords[i], yCoords[i]) | 1494 featureTrajectories[i].addPositionXY(xCoords[i], yCoords[i]) |
| 1398 # check https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga1019495a2c8d1743ed5cc23fa0daff8c | 1495 # check https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga1019495a2c8d1743ed5cc23fa0daff8c |
| 1399 if interval.length()>1: | 1496 objects.append(moving.MovingObject(num = max([o.getNum() for o in objects])+1, timeInterval = interval, positions = t, velocities = t.differentiate(True), userType = 'Car', features = [moving.MovingObject(num = featureNum+i, timeInterval = copy(interval), positions = featureTrajectories[i], velocities = featureTrajectories[i].differentiate(True)) for i in range(4)])) |
| 1400 objects.append(moving.MovingObject(num = objNum, timeInterval = interval, positions = t, velocities = t.differentiate(True), userType = userType, features = [moving.MovingObject(num = featureNum+i, timeInterval = copy(interval), positions = featureTrajectories[i], velocities = featureTrajectories[i].differentiate(True)) for i in range(4)])) | |
| 1401 featureNum += 4 | |
| 1402 | |
| 1403 # ego vehicle | |
| 1404 t = moving.Trajectory() | |
| 1405 featureTrajectories = [moving.Trajectory() for i in range(4)] | |
| 1406 interval = moving.TimeInterval(0, len(oxts)-1)#int(data.frame.min()), int(data.frame.max())) | |
| 1407 R = roty(pi/2) | |
| 1408 #for frame in interval: | |
| 1409 for _, Tr_imu_to_world in oxts: | |
| 1410 l = 4.5 # m | |
| 1411 w = 1.8 # m | |
| 1412 h = 0. | |
| 1413 # 3d bounding box corners | |
| 1414 x_corners = [l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2] | |
| 1415 y_corners = [0, 0, 0, 0, -h, -h, -h, -h] | |
| 1416 z_corners = [w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2] | |
| 1417 # rotate and translate 3d bounding box | |
| 1418 corners3d = dot(R, vstack([x_corners, y_corners, z_corners])) | |
| 1419 corners3d[0, :] = corners3d[0, :] | |
| 1420 corners3d[1, :] = corners3d[1, :] | |
| 1421 corners3d[2, :] = corners3d[2, :] | |
| 1422 refCorners = transpose(dot(invR0, corners3d)) # 8x3 avoid double transpose np.transpose(pts_3d_rect))) in pts_3d_ref = self.project_rect_to_ref(pts_3d_rect) | |
| 1423 homRefCorners = cartesian2Homogeneous(refCorners) | |
| 1424 veloCorners = dot(homRefCorners, transCam2Velo) | |
| 1425 homVeloCorners = cartesian2Homogeneous(veloCorners) | |
| 1426 imuCorners = dot(kittiCalibration['Tr_velo_imu'], homVeloCorners.T).T # 8x3 | |
| 1427 | |
| 1428 homImuCorners = cartesian2Homogeneous(imuCorners) | |
| 1429 worldCorners = dot(Tr_imu_to_world, homImuCorners.T).T # 8x3 | |
| 1430 | |
| 1431 # take first 4 lines of corners, x,y,_ # x0, y0, _ = boxes3d[0] | |
| 1432 xCoords = worldCorners[:4,0] | |
| 1433 yCoords = worldCorners[:4,1] | |
| 1434 t.addPositionXY(xCoords.mean(), yCoords.mean()) | |
| 1435 for i in range(4): | |
| 1436 featureTrajectories[i].addPositionXY(xCoords[i], yCoords[i]) | |
| 1437 # check https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga1019495a2c8d1743ed5cc23fa0daff8c | |
| 1438 objects.append(moving.MovingObject(num = max([o.getNum() for o in objects])+1, timeInterval = interval, positions = t, velocities = t.differentiate(True), userType = 'Car', features = [moving.MovingObject(num = featureNum+i, timeInterval = copy(interval), positions = featureTrajectories[i], velocities = featureTrajectories[i].differentiate(True)) for i in range(4)])) | |
| 1439 | 1497 |
| 1440 return objects | 1498 return objects |
| 1441 | 1499 |
| 1442 def loadTrajectoriesFromKITTI2D(filename, kittiCalibration = None, oxts = None): | 1500 def loadTrajectoriesFromKITTI2D(filename, kittiCalibration = None, oxts = None): |
| 1443 '''Loads x,y coordinate series | 1501 '''Loads x,y coordinate series |
