Mercurial Hosting > traffic-intelligence
changeset 588:c5406edbcf12
added loading ground truth annotations (ground truth) from polytrack format
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Fri, 05 Dec 2014 00:54:38 -0500 |
parents | cf578ba866da |
children | 5800a87f11ae 5e09583275a4 |
files | python/moving.py python/storage.py python/utils.py |
diffstat | 3 files changed, 66 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/python/moving.py Thu Dec 04 17:46:32 2014 -0500 +++ b/python/moving.py Fri Dec 05 00:54:38 2014 -0500 @@ -924,7 +924,8 @@ class MovingObject(STObject): '''Class for moving objects: a spatio-temporal object - with a trajectory and a geometry (constant volume over time) and a usertype (e.g. road user) coded as a number (see + with a trajectory and a geometry (constant volume over time) + and a usertype (e.g. road user) coded as a number (see userTypeNames) ''' def __init__(self, num = None, timeInterval = None, positions = None, velocities = None, geometry = None, userType = userType2Num['unknown']): @@ -1278,22 +1279,21 @@ ################## -# Bounding Boxes +# Annotations ################## -# class BoundingBoxes(STObject): -# '''Class for : a spatio-temporal object -# with a trajectory and a geometry (constant volume over time) and a usertype (e.g. road user) coded as a number (see -# ''' +class BBAnnotation(MovingObject): + '''Class for : a series of ground truth annotations using bounding boxes + Its center is the center of the containing shape + ''' -# def __init__(self, num = None, timeInterval = None, positions = None, velocities = None, geometry = None, userType = userType2Num['unknown']): -# super(MovingObject, self).__init__(num, timeInterval) -# self.positions = positions -# self.velocities = velocities -# self.geometry = geometry -# self.userType = userType -# self.features = [] -# # compute bounding polygon from trajectory + def __init__(self, num = None, timeInterval = None, topPositions = None, bottomPositions = None, userType = userType2Num['unknown']): + super(BBAnnotation, self).__init__(num, timeInterval, Trajectory(), userType = userType) + self.topPositions = topPositions.getPositions() + self.bottomPositions = bottomPositions.getPositions() + for i in xrange(int(topPositions.length())): + self.positions.addPosition((topPositions.getPositionAt(i) + bottomPositions.getPositionAt(i)).multiply(0.5)) + def plotRoadUsers(objects, colors): '''Colors is a PlottingPropertyValues instance'''
--- a/python/storage.py Thu Dec 04 17:46:32 2014 -0500 +++ b/python/storage.py Fri Dec 05 00:54:38 2014 -0500 @@ -34,6 +34,7 @@ except sqlite3.OperationalError as error: printDBError(error) +# TODO: add test if database connection is open # IO to sqlite def writeTrajectoriesToSqlite(objects, outputFilename, trajectoryType, objectNumbers = -1): """ @@ -271,16 +272,16 @@ cursor = connection.cursor() try: - trajectoryIdQuery = getTrajectoryIdQuery(objectNumbers, trajectoryType) + idQuery = getTrajectoryIdQuery(objectNumbers, trajectoryType) if trajectoryType == 'feature': - queryStatement = 'SELECT * from '+tableName+' '+trajectoryIdQuery+'ORDER BY trajectory_id, frame_number' + queryStatement = 'SELECT * from '+tableName+' '+idQuery+'ORDER BY trajectory_id, frame_number' cursor.execute(queryStatement) logging.debug(queryStatement) 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 '+objectIdQuery+'group by OF.object_id, P.frame_number ORDER BY OF.object_id, P.frame_number' + 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 '+idQuery+'group by OF.object_id, P.frame_number ORDER BY OF.object_id, P.frame_number' cursor.execute(queryStatement) logging.debug(queryStatement) - elif trajectoryType == 'bbtop' or trajectoryType == 'bbbottom': + elif trajectoryType in ['bbtop', 'bbbottom']: if trajectoryType == 'bbtop': corner = 'top_left' elif trajectoryType == 'bbbottom': @@ -300,21 +301,36 @@ for row in cursor: if row[0] != objId: objId = row[0] - if obj != None: + if obj != None and obj.length() == obj.positions.length(): objects.append(obj) + elif obj != None: + print('Object {} is missing {} positions'.format(obj.getNum(), int(obj.length())-obj.positions.length())) obj = moving.MovingObject(row[0], timeInterval = moving.TimeInterval(row[1], row[1]), positions = moving.Trajectory([[row[2]],[row[3]]])) else: obj.timeInterval.last = row[1] obj.positions.addPositionXY(row[2],row[3]) - if obj: + if obj != None and obj.length() == obj.positions.length(): objects.append(obj) + elif obj != None: + print('Object {} is missing {} positions'.format(obj.getNum(), int(obj.length())-obj.positions.length())) return objects +def loadUserTypesFromTable(cursor, trajectoryType, objectNumbers): + objectIdQuery = getTrajectoryIdQuery(objectNumbers, trajectoryType) + if objectIdQuery == '': + cursor.execute('SELECT object_id, road_user_type from objects') + else: + cursor.execute('SELECT object_id, road_user_type from objects where '+objectIdQuery[7:]) + userTypes = {} + for row in cursor: + userTypes[row[0]] = row[1] + return userTypes + def loadTrajectoriesFromSqlite(filename, trajectoryType, objectNumbers = None): '''Loads the first objectNumbers objects or the indices in objectNumbers from the database''' - connection = sqlite3.connect(filename) # add test if it open + connection = sqlite3.connect(filename) objects = loadTrajectoriesFromTable(connection, 'positions', trajectoryType, objectNumbers) objectVelocities = loadTrajectoriesFromTable(connection, 'velocities', trajectoryType, objectNumbers) @@ -348,24 +364,38 @@ obj.featureNumbers = featureNumbers[obj.getNum()] # load userType - if objectIdQuery == '': - cursor.execute('SELECT object_id, road_user_type from objects') - else: - cursor.execute('SELECT object_id, road_user_type from objects where '+objectIdQuery[7:]) - userTypes = {} - for row in cursor: - userTypes[row[0]] = row[1] - + userTypes = loadUserTypesFromTable(cursor, trajectoryType, objectNumbers) for obj in objects: obj.userType = userTypes[obj.getNum()] except sqlite3.OperationalError as error: printDBError(error) - return [] + objects = [] connection.close() return objects +def loadGroundTruthFromSqlite(filename, gtType, gtNumbers = None): + 'Loads bounding box annotations (ground truth) from an SQLite ' + connection = sqlite3.connect(filename) + gt = [] + + if gtType == 'bb': + topCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbtop', gtNumbers) + bottomCorners = loadTrajectoriesFromTable(connection, 'bounding_boxes', 'bbbottom', gtNumbers) + userTypes = loadUserTypesFromTable(connection.cursor(), 'object', gtNumbers) # string format is same as object + + for t, b in zip(topCorners, bottomCorners): + num = t.getNum() + if t.getNum() == b.getNum(): + annotation = moving.BBAnnotation(num, t.getTimeInterval(), t, b, userTypes[num]) + gt.append(annotation) + else: + print ('Unknown type of annotation {}'.format(gtType)) + + connection.close() + return gt + def deleteFromSqlite(filename, dataType): 'Deletes (drops) some tables in the filename depending on type of data' import os
--- a/python/utils.py Thu Dec 04 17:46:32 2014 -0500 +++ b/python/utils.py Fri Dec 05 00:54:38 2014 -0500 @@ -61,15 +61,13 @@ def nSamples(self): return sum(self.counts) -def cumulativeDensityFunction(sample): +def cumulativeDensityFunction(sample, normalized = False): '''Returns the cumulative density function of the sample of a random variable''' - from numpy.core.multiarray import array - from numpy.lib.function_base import unique - from numpy.core.fromnumeric import sum - a = array(sample) - a.sort() - xaxis = unique(a) - counts = [sum(a <= x) for x in xaxis] + from numpy import arange, cumsum + xaxis = sorted(sample) + counts = arange(1,len(sample)+1) # dtype = float + if normalized: + counts /= float(len(sample)) return xaxis, counts class EmpiricalDiscreteDistribution(EmpiricalDistribution):