changeset 834:119c4efe6398

added option to load subsampled trajectories
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Thu, 30 Jun 2016 14:19:59 -0400
parents 8d1dd771aeb3
children f3ae72d86762
files python/storage.py python/tests/storage.txt
diffstat 2 files changed, 34 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/python/storage.py	Thu Jun 30 14:01:13 2016 -0400
+++ b/python/storage.py	Thu Jun 30 14:19:59 2016 -0400
@@ -7,7 +7,7 @@
 
 from os import path
 import sqlite3, logging
-from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt
+from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt, floor as npfloor, ceil as npceil
 from pandas import read_csv, merge
 
 
@@ -145,7 +145,7 @@
         query = ''
     return query
 
-def loadTrajectoriesFromTable(connection, tableName, trajectoryType, objectNumbers = None):
+def loadTrajectoriesFromTable(connection, tableName, trajectoryType, objectNumbers = None, timeStep = None):
     '''Loads trajectories (in the general sense) from the given table
     can be positions or velocities
 
@@ -157,13 +157,19 @@
         queryStatement = None
         if trajectoryType == 'feature':
             queryStatement = 'SELECT * from '+tableName
-            if objectNumbers is not None:
+            if objectNumbers is not None and timeStep is not None:
+                queryStatement += ' WHERE trajectory_id '+objectCriteria+' AND frame_number%{} = 0'.format(timeStep)
+            elif objectNumbers is not None:
                 queryStatement += ' WHERE trajectory_id '+objectCriteria
+            elif timeStep is not None:
+                queryStatement += ' WHERE frame_number%{} = 0'.format(timeStep)
             queryStatement += ' ORDER BY trajectory_id, frame_number'
         elif trajectoryType == 'object':
             queryStatement = 'SELECT OF.object_id, P.frame_number, avg(P.x_coordinate), avg(P.y_coordinate) from '+tableName+' P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id'
             if objectNumbers is not None:
-                queryStatement += ' and OF.object_id '+objectCriteria
+                queryStatement += ' AND OF.object_id '+objectCriteria
+            if timeStep is not None:
+                queryStatement += ' AND P.frame_number%{} = 0'.format(timeStep)
             queryStatement += ' GROUP BY OF.object_id, P.frame_number ORDER BY OF.object_id, P.frame_number'
         elif trajectoryType in ['bbtop', 'bbbottom']:
             if trajectoryType == 'bbtop':
@@ -171,8 +177,12 @@
             elif trajectoryType == 'bbbottom':
                 corner = 'bottom_right'
             queryStatement = 'SELECT object_id, frame_number, x_'+corner+', y_'+corner+' FROM '+tableName
-            if objectNumbers is not None:
+            if objectNumbers is not None and timeStep is not None:
+                queryStatement += ' WHERE object_id '+objectCriteria+' AND frame_number%{} = 0'.format(timeStep)
+            elif objectNumbers is not None:
                 queryStatement += ' WHERE object_id '+objectCriteria
+            elif timeStep is not None:
+                queryStatement += ' WHERE frame_number%{} = 0'.format(timeStep)
             queryStatement += ' ORDER BY object_id, frame_number'
         else:
             print('Unknown trajectory type {}'.format(trajectoryType))
@@ -189,7 +199,7 @@
     for row in cursor:
         if row[0] != objId:
             objId = row[0]
-            if obj is not None and obj.length() == obj.positions.length():
+            if obj is not None and (obj.length() == obj.positions.length() or (timeStep is not None and npceil(obj.length()/timeStep) == obj.positions.length())):
                 objects.append(obj)
             elif obj is not None:
                 print('Object {} is missing {} positions'.format(obj.getNum(), int(obj.length())-obj.positions.length()))
@@ -198,7 +208,7 @@
             obj.timeInterval.last = row[1]
             obj.positions.addPositionXY(row[2],row[3])
 
-    if obj is not None and obj.length() == obj.positions.length():
+    if obj is not None and (obj.length() == obj.positions.length() or (timeStep is not None and npceil(obj.length()/timeStep) == obj.positions.length())):
         objects.append(obj)
     elif obj is not None:
         print('Object {} is missing {} positions'.format(obj.getNum(), int(obj.length())-obj.positions.length()))
@@ -216,15 +226,15 @@
         userTypes[row[0]] = row[1]
     return userTypes
 
-def loadTrajectoriesFromSqlite(filename, trajectoryType, objectNumbers = None, withFeatures = False):
+def loadTrajectoriesFromSqlite(filename, trajectoryType, objectNumbers = None, withFeatures = False, timeStep = None):
     '''Loads the trajectories (in the general sense, 
     either features, objects (feature groups) or bounding box series) 
     The number loaded is either the first objectNumbers objects,
     or the indices in objectNumbers from the database'''
     connection = sqlite3.connect(filename)
 
-    objects = loadTrajectoriesFromTable(connection, 'positions', trajectoryType, objectNumbers)
-    objectVelocities = loadTrajectoriesFromTable(connection, 'velocities', trajectoryType, objectNumbers)
+    objects = loadTrajectoriesFromTable(connection, 'positions', trajectoryType, objectNumbers, timeStep)
+    objectVelocities = loadTrajectoriesFromTable(connection, 'velocities', trajectoryType, objectNumbers, timeStep)
 
     if len(objectVelocities) > 0:
         for o,v in zip(objects, objectVelocities):
@@ -266,7 +276,7 @@
                 nFeatures = 0
                 for obj in objects:
                     nFeatures = max(nFeatures, max(obj.featureNumbers))
-                features = loadTrajectoriesFromSqlite(filename, 'feature', nFeatures+1)
+                features = loadTrajectoriesFromSqlite(filename, 'feature', nFeatures+1, timeStep = timeStep)
                 for obj in objects:
                     obj.setFeatures(features)
              
@@ -370,7 +380,7 @@
 def loadPrototypesFromSqlite(filename):
     pass
 
-def loadBBMovingObjectsFromSqlite(filename, objectType = 'bb', objectNumbers = None):
+def loadBBMovingObjectsFromSqlite(filename, objectType = 'bb', objectNumbers = None, timeStep = None):
     '''Loads bounding box moving object from an SQLite
     (format of SQLite output by the ground truth annotation tool
     or Urban Tracker
@@ -380,8 +390,8 @@
     objects = []
 
     if objectType == 'bb':
-        topCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbtop', objectNumbers)
-        bottomCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbbottom', objectNumbers)
+        topCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbtop', objectNumbers, timeStep)
+        bottomCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbbottom', objectNumbers, timeStep)
         userTypes = loadUserTypesFromTable(connection.cursor(), 'object', objectNumbers) # string format is same as object
         
         for t, b in zip(topCorners, bottomCorners):
--- a/python/tests/storage.txt	Thu Jun 30 14:01:13 2016 -0400
+++ b/python/tests/storage.txt	Thu Jun 30 14:19:59 2016 -0400
@@ -38,6 +38,16 @@
 True
 >>> o2.getPositions() == objects[1].getPositions()
 True
+>>> objects = loadTrajectoriesFromSqlite('test.sqlite', 'feature', timeStep = 2)
+>>> objects[0].positions.length()
+6
+>>> objects[1].positions.length()
+5
+>>> objects = loadTrajectoriesFromSqlite('test.sqlite', 'feature', timeStep = 3)
+>>> objects[0].positions.length()
+4
+>>> objects[1].positions.length()
+4
 >>> align1 = Trajectory.fromPointList([Point(-1, 0), Point(20, 0)])
 >>> align2 = Trajectory.fromPointList([Point(-9, -3), Point(6, 3)])
 >>> align1.computeCumulativeDistances()