comparison trafficintelligence/storage.py @ 1050:9d4a06f49cb8

work in progress
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Fri, 06 Jul 2018 18:12:15 -0400
parents c9c03c97ed9f
children 9e4e80fc5943
comparison
equal deleted inserted replaced
1049:c9c03c97ed9f 1050:9d4a06f49cb8
257 if object, features can be loaded with withFeatures or nLongestObjectFeatures used to select the n longest features 257 if object, features can be loaded with withFeatures or nLongestObjectFeatures used to select the n longest features
258 258
259 The number loaded is either the first objectNumbers objects, 259 The number loaded is either the first objectNumbers objects,
260 or the indices in objectNumbers from the database''' 260 or the indices in objectNumbers from the database'''
261 objects = [] 261 objects = []
262 with sqlite3.connect(filename) as connection: 262 if Path(filename).exists():
263 objects = loadTrajectoriesFromTable(connection, 'positions', trajectoryType, objectNumbers, timeStep) 263 with sqlite3.connect(filename) as connection:
264 objectVelocities = loadTrajectoriesFromTable(connection, 'velocities', trajectoryType, objectNumbers, timeStep) 264 objects = loadTrajectoriesFromTable(connection, 'positions', trajectoryType, objectNumbers, timeStep)
265 265 objectVelocities = loadTrajectoriesFromTable(connection, 'velocities', trajectoryType, objectNumbers, timeStep)
266 if len(objectVelocities) > 0: 266
267 for o,v in zip(objects, objectVelocities): 267 if len(objectVelocities) > 0:
268 if o.getNum() == v.getNum(): 268 for o,v in zip(objects, objectVelocities):
269 o.velocities = v.positions 269 if o.getNum() == v.getNum():
270 o.velocities.duplicateLastPosition() # avoid having velocity shorter by one position than positions 270 o.velocities = v.positions
271 else: 271 o.velocities.duplicateLastPosition() # avoid having velocity shorter by one position than positions
272 print('Could not match positions {0} with velocities {1}'.format(o.getNum(), v.getNum()))
273
274 if trajectoryType == 'object':
275 cursor = connection.cursor()
276 try:
277 # attribute feature numbers to objects
278 queryStatement = 'SELECT trajectory_id, object_id FROM objects_features'
279 if objectNumbers is not None:
280 queryStatement += ' WHERE object_id '+getObjectCriteria(objectNumbers)
281 queryStatement += ' ORDER BY object_id' # order is important to group all features per object
282 logging.debug(queryStatement)
283 cursor.execute(queryStatement)
284
285 featureNumbers = {}
286 for row in cursor:
287 objId = row[1]
288 if objId not in featureNumbers:
289 featureNumbers[objId] = [row[0]]
290 else: 272 else:
291 featureNumbers[objId].append(row[0]) 273 print('Could not match positions {0} with velocities {1}'.format(o.getNum(), v.getNum()))
292 274
293 for obj in objects: 275 if trajectoryType == 'object':
294 obj.featureNumbers = featureNumbers[obj.getNum()] 276 cursor = connection.cursor()
295 277 try:
296 # load userType 278 # attribute feature numbers to objects
297 attributes = loadObjectAttributesFromTable(cursor, objectNumbers, True) 279 queryStatement = 'SELECT trajectory_id, object_id FROM objects_features'
298 for obj in objects: 280 if objectNumbers is not None:
299 userType, nObjects = attributes[obj.getNum()] 281 queryStatement += ' WHERE object_id '+getObjectCriteria(objectNumbers)
300 obj.setUserType(userType) 282 queryStatement += ' ORDER BY object_id' # order is important to group all features per object
301 obj.setNObjects(nObjects) 283 logging.debug(queryStatement)
302 284 cursor.execute(queryStatement)
303 # add features 285
304 if withFeatures: 286 featureNumbers = {}
287 for row in cursor:
288 objId = row[1]
289 if objId not in featureNumbers:
290 featureNumbers[objId] = [row[0]]
291 else:
292 featureNumbers[objId].append(row[0])
293
305 for obj in objects: 294 for obj in objects:
306 obj.features = loadTrajectoriesFromSqlite(filename, 'feature', obj.featureNumbers, timeStep = timeStep) 295 obj.featureNumbers = featureNumbers[obj.getNum()]
307 elif nLongestFeaturesPerObject is not None: 296
297 # load userType
298 attributes = loadObjectAttributesFromTable(cursor, objectNumbers, True)
308 for obj in objects: 299 for obj in objects:
309 queryStatement = 'SELECT trajectory_id, max(frame_number)-min(frame_number) AS length FROM positions WHERE trajectory_id '+getObjectCriteria(obj.featureNumbers)+' GROUP BY trajectory_id ORDER BY length DESC' 300 userType, nObjects = attributes[obj.getNum()]
310 logging.debug(queryStatement) 301 obj.setUserType(userType)
311 cursor.execute(queryStatement) 302 obj.setNObjects(nObjects)
312 obj.features = loadTrajectoriesFromSqlite(filename, 'feature', [row[0] for i,row in enumerate(cursor) if i<nLongestFeaturesPerObject], timeStep = timeStep) 303
313 304 # add features
314 except sqlite3.OperationalError as error: 305 if withFeatures:
315 printDBError(error) 306 for obj in objects:
307 obj.features = loadTrajectoriesFromSqlite(filename, 'feature', obj.featureNumbers, timeStep = timeStep)
308 elif nLongestFeaturesPerObject is not None:
309 for obj in objects:
310 queryStatement = 'SELECT trajectory_id, max(frame_number)-min(frame_number) AS length FROM positions WHERE trajectory_id '+getObjectCriteria(obj.featureNumbers)+' GROUP BY trajectory_id ORDER BY length DESC'
311 logging.debug(queryStatement)
312 cursor.execute(queryStatement)
313 obj.features = loadTrajectoriesFromSqlite(filename, 'feature', [row[0] for i,row in enumerate(cursor) if i<nLongestFeaturesPerObject], timeStep = timeStep)
314
315 except sqlite3.OperationalError as error:
316 printDBError(error)
316 return objects 317 return objects
317 318
318 def loadObjectFeatureFrameNumbers(filename, objectNumbers = None): 319 def loadObjectFeatureFrameNumbers(filename, objectNumbers = None):
319 'Loads the feature frame numbers for each object' 320 'Loads the feature frame numbers for each object'
320 with sqlite3.connect(filename) as connection: 321 with sqlite3.connect(filename) as connection:
449 (format of SQLite output by the ground truth annotation tool 450 (format of SQLite output by the ground truth annotation tool
450 or Urban Tracker 451 or Urban Tracker
451 452
452 Load descriptions?''' 453 Load descriptions?'''
453 objects = [] 454 objects = []
454 with sqlite3.connect(filename) as connection: 455 if Path(filename).exists():
455 if objectType == 'bb': 456 with sqlite3.connect(filename) as connection:
456 topCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbtop', objectNumbers, timeStep) 457 if objectType == 'bb':
457 bottomCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbbottom', objectNumbers, timeStep) 458 topCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbtop', objectNumbers, timeStep)
458 userTypes = loadObjectAttributesFromTable(connection.cursor(), objectNumbers) # string format is same as object 459 bottomCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbbottom', objectNumbers, timeStep)
459 460 userTypes = loadObjectAttributesFromTable(connection.cursor(), objectNumbers) # string format is same as object
460 for t, b in zip(topCorners, bottomCorners): 461
461 num = t.getNum() 462 for t, b in zip(topCorners, bottomCorners):
462 if t.getNum() == b.getNum(): 463 num = t.getNum()
463 annotation = moving.BBMovingObject(num, t.getTimeInterval(), t, b, userTypes[num]) 464 if t.getNum() == b.getNum():
464 objects.append(annotation) 465 annotation = moving.BBMovingObject(num, t.getTimeInterval(), t, b, userTypes[num])
465 else: 466 objects.append(annotation)
466 print ('Unknown type of bounding box {}'.format(objectType)) 467 else:
468 print ('Unknown type of bounding box {}'.format(objectType))
467 return objects 469 return objects
468 470
469 def saveInteraction(cursor, interaction): 471 def saveInteraction(cursor, interaction):
470 roadUserNumbers = list(interaction.getRoadUserNumbers()) 472 roadUserNumbers = list(interaction.getRoadUserNumbers())
471 cursor.execute('INSERT INTO interactions VALUES({}, {}, {}, {}, {})'.format(interaction.getNum(), roadUserNumbers[0], roadUserNumbers[1], interaction.getFirstInstant(), interaction.getLastInstant())) 473 cursor.execute('INSERT INTO interactions VALUES({}, {}, {}, {}, {})'.format(interaction.getNum(), roadUserNumbers[0], roadUserNumbers[1], interaction.getFirstInstant(), interaction.getLastInstant()))
507 def loadInteractionsFromSqlite(filename): 509 def loadInteractionsFromSqlite(filename):
508 '''Loads interaction and their indicators 510 '''Loads interaction and their indicators
509 511
510 TODO choose the interactions to load''' 512 TODO choose the interactions to load'''
511 interactions = [] 513 interactions = []
512 with sqlite3.connect(filename) as connection: 514 if Path(filename).exists():
513 cursor = connection.cursor() 515 with sqlite3.connect(filename) as connection:
514 try: 516 cursor = connection.cursor()
515 cursor.execute('SELECT INT.id, INT.object_id1, INT.object_id2, INT.first_frame_number, INT.last_frame_number, IND.indicator_type, IND.frame_number, IND.value from interactions INT, indicators IND WHERE INT.id = IND.interaction_id ORDER BY INT.id, IND.indicator_type, IND.frame_number') 517 try:
516 interactionNum = -1 518 cursor.execute('SELECT INT.id, INT.object_id1, INT.object_id2, INT.first_frame_number, INT.last_frame_number, IND.indicator_type, IND.frame_number, IND.value from interactions INT, indicators IND WHERE INT.id = IND.interaction_id ORDER BY INT.id, IND.indicator_type, IND.frame_number')
517 indicatorTypeNum = -1 519 interactionNum = -1
518 tmpIndicators = {} 520 indicatorTypeNum = -1
519 for row in cursor: 521 tmpIndicators = {}
520 if row[0] != interactionNum: 522 for row in cursor:
521 interactionNum = row[0] 523 if row[0] != interactionNum:
522 interactions.append(events.Interaction(interactionNum, moving.TimeInterval(row[3],row[4]), row[1], row[2])) 524 interactionNum = row[0]
523 interactions[-1].indicators = {} 525 interactions.append(events.Interaction(interactionNum, moving.TimeInterval(row[3],row[4]), row[1], row[2]))
524 if indicatorTypeNum != row[5] or row[0] != interactionNum: 526 interactions[-1].indicators = {}
525 indicatorTypeNum = row[5] 527 if indicatorTypeNum != row[5] or row[0] != interactionNum:
526 indicatorName = events.Interaction.indicatorNames[indicatorTypeNum] 528 indicatorTypeNum = row[5]
527 indicatorValues = {row[6]:row[7]} 529 indicatorName = events.Interaction.indicatorNames[indicatorTypeNum]
528 interactions[-1].indicators[indicatorName] = indicators.SeverityIndicator(indicatorName, indicatorValues, mostSevereIsMax = not indicatorName in events.Interaction.timeIndicators) 530 indicatorValues = {row[6]:row[7]}
529 else: 531 interactions[-1].indicators[indicatorName] = indicators.SeverityIndicator(indicatorName, indicatorValues, mostSevereIsMax = not indicatorName in events.Interaction.timeIndicators)
530 indicatorValues[row[6]] = row[7] 532 else:
531 interactions[-1].indicators[indicatorName].timeInterval.last = row[6] 533 indicatorValues[row[6]] = row[7]
532 except sqlite3.OperationalError as error: 534 interactions[-1].indicators[indicatorName].timeInterval.last = row[6]
533 printDBError(error) 535 except sqlite3.OperationalError as error:
534 return [] 536 printDBError(error)
537 return []
535 return interactions 538 return interactions
536 # load first and last object instants 539 # load first and last object instants
537 # CREATE TEMP TABLE IF NOT EXISTS object_instants AS SELECT OF.object_id, min(frame_number) as first_instant, max(frame_number) as last_instant from positions P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id group by OF.object_id order by OF.object_id 540 # CREATE TEMP TABLE IF NOT EXISTS object_instants AS SELECT OF.object_id, min(frame_number) as first_instant, max(frame_number) as last_instant from positions P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id group by OF.object_id order by OF.object_id
538 541
539 def createBoundingBoxTable(filename, invHomography = None): 542 def createBoundingBoxTable(filename, invHomography = None):
552 connection.commit() 555 connection.commit()
553 556
554 def loadBoundingBoxTableForDisplay(filename): 557 def loadBoundingBoxTableForDisplay(filename):
555 '''Loads bounding boxes from bounding_boxes table for display over trajectories''' 558 '''Loads bounding boxes from bounding_boxes table for display over trajectories'''
556 boundingBoxes = {} # list of bounding boxes for each instant 559 boundingBoxes = {} # list of bounding boxes for each instant
557 with sqlite3.connect(filename) as connection: 560 if Path(filename).exists():
558 cursor = connection.cursor() 561 with sqlite3.connect(filename) as connection:
559 try: 562 cursor = connection.cursor()
560 cursor.execute('SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'bounding_boxes\'') 563 try:
561 result = cursor.fetchall() 564 cursor.execute('SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'bounding_boxes\'')
562 if len(result) > 0: 565 result = cursor.fetchall()
563 cursor.execute('SELECT * FROM bounding_boxes') 566 if len(result) > 0:
564 for row in cursor: 567 cursor.execute('SELECT * FROM bounding_boxes')
565 boundingBoxes.setdefault(row[1], []).append([moving.Point(row[2], row[3]), moving.Point(row[4], row[5])]) 568 for row in cursor:
566 except sqlite3.OperationalError as error: 569 boundingBoxes.setdefault(row[1], []).append([moving.Point(row[2], row[3]), moving.Point(row[4], row[5])])
567 printDBError(error) 570 except sqlite3.OperationalError as error:
568 return boundingBoxes 571 printDBError(error)
569 return boundingBoxes 572 return boundingBoxes
570 573
571 ######################### 574 #########################
572 # saving and loading for scene interpretation: POIs and Prototypes 575 # saving and loading for scene interpretation: POIs and Prototypes
573 ######################### 576 #########################
622 except sqlite3.OperationalError as error: 625 except sqlite3.OperationalError as error:
623 printDBError(error) 626 printDBError(error)
624 connection.commit() 627 connection.commit()
625 628
626 def loadPrototypeAssignmentsFromSqlite(filename, objectType): 629 def loadPrototypeAssignmentsFromSqlite(filename, objectType):
627 with sqlite3.connect(filename) as connection: 630 prototypeAssignments = {}
628 cursor = connection.cursor() 631 if Path(filename).exists():
629 try: 632 with sqlite3.connect(filename) as connection:
630 tableName, objectIdColumnName = prototypeAssignmentNames(objectType) 633 cursor = connection.cursor()
631 cursor.execute('SELECT * FROM '+tableName) 634 try:
632 prototypeAssignments = {} 635 tableName, objectIdColumnName = prototypeAssignmentNames(objectType)
633 for row in cursor: 636 cursor.execute('SELECT * FROM '+tableName)
634 p = moving.Prototype(row[1], row[2], row[3]) 637 for row in cursor:
635 if p in prototypeAssignments: 638 p = moving.Prototype(row[1], row[2], row[3])
636 prototypeAssignments[p].append(row[0]) 639 if p in prototypeAssignments:
637 else: 640 prototypeAssignments[p].append(row[0])
638 prototypeAssignments[p] = [row[0]] 641 else:
639 return prototypeAssignments 642 prototypeAssignments[p] = [row[0]]
640 except sqlite3.OperationalError as error: 643 return prototypeAssignments
641 printDBError(error) 644 except sqlite3.OperationalError as error:
642 645 printDBError(error)
646 return prototypeAssignments
647
643 def loadPrototypesFromSqlite(filename, withTrajectories = True): 648 def loadPrototypesFromSqlite(filename, withTrajectories = True):
644 'Loads prototype ids and matchings (if stored)' 649 'Loads prototype ids and matchings (if stored)'
645 prototypes = [] 650 prototypes = []
646 with sqlite3.connect(filename) as connection: 651 if Path(filename).exists():
647 cursor = connection.cursor() 652 with sqlite3.connect(filename) as connection:
648 objects = [] 653 cursor = connection.cursor()
649 try: 654 objects = []
650 cursor.execute('SELECT * FROM prototypes') 655 try:
651 for row in cursor: 656 cursor.execute('SELECT * FROM prototypes')
652 prototypes.append(moving.Prototype(row[0], row[1], row[2], row[3])) 657 for row in cursor:
653 if withTrajectories: 658 prototypes.append(moving.Prototype(row[0], row[1], row[2], row[3]))
654 for p in prototypes: 659 if withTrajectories:
655 p.setMovingObject(loadTrajectoriesFromSqlite(p.getFilename(), p.getTrajectoryType(), [p.getNum()])[0]) 660 for p in prototypes:
656 # loadingInformation = {} # complicated slightly optimized 661 p.setMovingObject(loadTrajectoriesFromSqlite(p.getFilename(), p.getTrajectoryType(), [p.getNum()])[0])
657 # for p in prototypes: 662 # loadingInformation = {} # complicated slightly optimized
658 # dbfn = p.getFilename() 663 # for p in prototypes:
659 # trajType = p.getTrajectoryType() 664 # dbfn = p.getFilename()
660 # if (dbfn, trajType) in loadingInformation: 665 # trajType = p.getTrajectoryType()
661 # loadingInformation[(dbfn, trajType)].append(p) 666 # if (dbfn, trajType) in loadingInformation:
662 # else: 667 # loadingInformation[(dbfn, trajType)].append(p)
663 # loadingInformation[(dbfn, trajType)] = [p] 668 # else:
664 # for k, v in loadingInformation.iteritems(): 669 # loadingInformation[(dbfn, trajType)] = [p]
665 # objects += loadTrajectoriesFromSqlite(k[0], k[1], [p.getNum() for p in v]) 670 # for k, v in loadingInformation.iteritems():
666 except sqlite3.OperationalError as error: 671 # objects += loadTrajectoriesFromSqlite(k[0], k[1], [p.getNum() for p in v])
667 printDBError(error) 672 except sqlite3.OperationalError as error:
668 if len(set([p.getTrajectoryType() for p in prototypes])) > 1: 673 printDBError(error)
669 print('Different types of prototypes in database ({}).'.format(set([p.getTrajectoryType() for p in prototypes]))) 674 if len(set([p.getTrajectoryType() for p in prototypes])) > 1:
675 print('Different types of prototypes in database ({}).'.format(set([p.getTrajectoryType() for p in prototypes])))
670 return prototypes 676 return prototypes
671 677
672 def savePOIsToSqlite(filename, gmm, gmmType, gmmId): 678 def savePOIsToSqlite(filename, gmm, gmmType, gmmId):
673 '''Saves a Gaussian mixture model (of class sklearn.mixture.GaussianMixture) 679 '''Saves a Gaussian mixture model (of class sklearn.mixture.GaussianMixture)
674 gmmType is a type of GaussianMixture, learnt either from beginnings or ends of trajectories''' 680 gmmType is a type of GaussianMixture, learnt either from beginnings or ends of trajectories'''
701 def loadPOIsFromSqlite(filename): 707 def loadPOIsFromSqlite(filename):
702 'Loads all 2D Gaussians in the database' 708 'Loads all 2D Gaussians in the database'
703 from sklearn import mixture # todo if not avalaible, load data in duck-typed class with same fields 709 from sklearn import mixture # todo if not avalaible, load data in duck-typed class with same fields
704 from ast import literal_eval 710 from ast import literal_eval
705 pois = [] 711 pois = []
706 with sqlite3.connect(filename) as connection: 712 if Path(filename).exists():
707 cursor = connection.cursor() 713 with sqlite3.connect(filename) as connection:
708 try: 714 cursor = connection.cursor()
709 cursor.execute('SELECT * from gaussians2d') 715 try:
710 gmmId = None 716 cursor.execute('SELECT * from gaussians2d')
711 gmm = [] 717 gmmId = None
712 for row in cursor: 718 gmm = []
713 if gmmId is None or row[0] != gmmId: 719 for row in cursor:
714 if len(gmm) > 0: 720 if gmmId is None or row[0] != gmmId:
715 tmp = mixture.GaussianMixture(len(gmm), covarianceType) 721 if len(gmm) > 0:
716 tmp.means_ = array([gaussian['mean'] for gaussian in gmm]) 722 tmp = mixture.GaussianMixture(len(gmm), covarianceType)
717 tmp.covariances_ = array([gaussian['covar'] for gaussian in gmm]) 723 tmp.means_ = array([gaussian['mean'] for gaussian in gmm])
718 tmp.weights_ = array([gaussian['weight'] for gaussian in gmm]) 724 tmp.covariances_ = array([gaussian['covar'] for gaussian in gmm])
719 tmp.gmmTypes = [gaussian['type'] for gaussian in gmm] 725 tmp.weights_ = array([gaussian['weight'] for gaussian in gmm])
720 tmp.precisions_cholesky_ = array([gaussian['precisions'] for gaussian in gmm]) 726 tmp.gmmTypes = [gaussian['type'] for gaussian in gmm]
721 pois.append(tmp) 727 tmp.precisions_cholesky_ = array([gaussian['precisions'] for gaussian in gmm])
722 gaussian = {'type': row[2], 728 pois.append(tmp)
723 'mean': row[3:5], 729 gaussian = {'type': row[2],
724 'covar': array(literal_eval(row[5])), 730 'mean': row[3:5],
725 'weight': row[7], 731 'covar': array(literal_eval(row[5])),
726 'precisions': array(literal_eval(row[8]))} 732 'weight': row[7],
727 gmm = [gaussian] 733 'precisions': array(literal_eval(row[8]))}
728 covarianceType = row[6] 734 gmm = [gaussian]
729 gmmId = row[0] 735 covarianceType = row[6]
730 else: 736 gmmId = row[0]
731 gmm.append({'type': row[2], 737 else:
732 'mean': row[3:5], 738 gmm.append({'type': row[2],
733 'covar': array(literal_eval(row[5])), 739 'mean': row[3:5],
734 'weight': row[7], 740 'covar': array(literal_eval(row[5])),
735 'precisions': array(literal_eval(row[8]))}) 741 'weight': row[7],
736 if len(gmm) > 0: 742 'precisions': array(literal_eval(row[8]))})
737 tmp = mixture.GaussianMixture(len(gmm), covarianceType) 743 if len(gmm) > 0:
738 tmp.means_ = array([gaussian['mean'] for gaussian in gmm]) 744 tmp = mixture.GaussianMixture(len(gmm), covarianceType)
739 tmp.covariances_ = array([gaussian['covar'] for gaussian in gmm]) 745 tmp.means_ = array([gaussian['mean'] for gaussian in gmm])
740 tmp.weights_ = array([gaussian['weight'] for gaussian in gmm]) 746 tmp.covariances_ = array([gaussian['covar'] for gaussian in gmm])
741 tmp.gmmTypes = [gaussian['type'] for gaussian in gmm] 747 tmp.weights_ = array([gaussian['weight'] for gaussian in gmm])
742 tmp.precisions_cholesky_ = array([gaussian['precisions'] for gaussian in gmm]) 748 tmp.gmmTypes = [gaussian['type'] for gaussian in gmm]
743 pois.append(tmp) 749 tmp.precisions_cholesky_ = array([gaussian['precisions'] for gaussian in gmm])
744 except sqlite3.OperationalError as error: 750 pois.append(tmp)
745 printDBError(error) 751 except sqlite3.OperationalError as error:
752 printDBError(error)
746 return pois 753 return pois
747 754
748 ######################### 755 #########################
749 # saving and loading for scene interpretation (Mohamed Gomaa Mohamed's PhD) 756 # saving and loading for scene interpretation (Mohamed Gomaa Mohamed's PhD)
750 ######################### 757 #########################