changeset 921:630934595871

work in progress with prototype class
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Wed, 05 Jul 2017 18:01:43 -0400
parents 499154254f37
children acb5379c5fd7
files python/moving.py python/storage.py scripts/learn-motion-patterns.py
diffstat 3 files changed, 60 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/python/moving.py	Wed Jul 05 16:30:04 2017 -0400
+++ b/python/moving.py	Wed Jul 05 18:01:43 2017 -0400
@@ -1662,6 +1662,30 @@
                             movingObject2.getVelocityAtInstant(instant)-movingObject1.getVelocityAtInstant(instant)) #deltav
 
 
+class Prototype(object):
+    'Class for a prototype'
+
+    def __init__(self, filename, num, trajectoryType, nMatchings = None):
+        self.filename = filename
+        self.num = num
+        self.trajectoryType = trajectoryType
+        self.nMatchings = nMatchings
+        self.movingObject = None
+
+    def getFilename(self):
+        return self.filename
+    def getNum(self):
+        return self.num
+    def getTrajectoryType(self):
+        return self.trajectoryType
+    def getNMatchings(self):
+        return self.nMatchings
+    def getMovingObject(self):
+        return self.movingObject
+    def setMovingObject(self, o):
+        self.movingObject = o
+
+    
 ##################
 # Annotations
 ##################
--- a/python/storage.py	Wed Jul 05 16:30:04 2017 -0400
+++ b/python/storage.py	Wed Jul 05 18:01:43 2017 -0400
@@ -592,29 +592,14 @@
 # saving and loading for scene interpretation: POIs and Prototypes
 #########################
 
-def savePrototypesToSqlite(filename, prototypeIndices, trajectoryType, nMatchings = None, dbFilenames = None):
-    '''save the prototype indices
-    if objects is not None, the trajectories are also saved in prototype_positions and _velocities
-    (prototypeIndices have to be in objects
-    objects will be saved as features, with the centroid trajectory as if it is a feature)
-    nMatchings, if not None, is a list of the number of matches
-    dbFilenames, if not None, is a list of the DB filenames
-
-    The order of prototypeIndices, objects, nMatchings and dbFilenames should be consistent'''
+def savePrototypesToSqlite(filename, prototypes):
+    '''save the prototypes (a prototype is defined by a filename, a number and type'''
     connection = sqlite3.connect(filename)
     cursor = connection.cursor()
     try:
-        cursor.execute('CREATE TABLE IF NOT EXISTS prototypes (id INTEGER, dbfilename VARCHAR, trajectory_type VARCHAR CHECK (trajectory_type IN (\"feature\", \"object\")), nmatchings INTEGER, PRIMARY KEY (id, dbfilename))')
-        for i, protoId in enumerate(prototypeIndices):
-            if nMatchings is not None:
-                n = nMatchings[i]
-            else:
-                n = 'NULL'
-            if dbFilenames is not None:
-                dbfn = dbFilenames[i]
-            else:
-                dbfn = filename
-            cursor.execute('INSERT INTO prototypes (id, dbfilename, trajectory_type, nmatchings) VALUES (?,?,?,?)', (protoId, dbfn, trajectoryType, n))
+        cursor.execute('CREATE TABLE IF NOT EXISTS prototypes (dbfilename VARCHAR, id INTEGER, trajectory_type VARCHAR CHECK (trajectory_type IN (\"feature\", \"object\")), nmatchings INTEGER, PRIMARY KEY (id, dbfilename))')
+        for p in prototypes:
+            cursor.execute('INSERT INTO prototypes (dbfilename, id, trajectory_type, nmatchings) VALUES (?,?,?,?)', (p.getFilename(), p.getNum(), p.getTrajectoryType(), p.getNMatchings()))
     except sqlite3.OperationalError as error:
         printDBError(error)
     connection.commit()
@@ -627,34 +612,31 @@
     'Loads prototype ids and matchings (if stored)'
     connection = sqlite3.connect(filename)
     cursor = connection.cursor()
-    prototypeIndices = []
-    dbFilenames = []
-    trajectoryTypes = []
-    nMatchings = []
+    prototypes = []
     objects = []
     try:
         cursor.execute('SELECT * FROM prototypes')
         for row in cursor:
-            prototypeIndices.append(row[0])
-            dbFilenames.append(row[1])
-            trajectoryTypes.append(row[2])
-            if row[3] is not None:
-                nMatchings.append(row[3])
+            prototypes.append(moving.Prototype(row[0], row[1], row[2], row[3]))
         if withTrajectories:
-            loadingInformation = {}
-            for dbfn, trajType, protoId in zip(dbFilenames, trajectoryTypes, prototypeIndices):
-                if (dbfn, trajType) in loadingInformation:
-                    loadingInformation[(dbfn, trajType)].append(protoId)
-                else:
-                    loadingInformation[(dbfn, trajType)] = [protoId]
-            for k, v in loadingInformation.iteritems():
-                objects += loadTrajectoriesFromSqlite(k[0], k[1], v)
+            for p in prototypes:
+                p.setMovingObject(loadTrajectoriesFromSqlite(p.getFilename(), p.getTrajectoryType(), [p.getNum()])[0])
+            # loadingInformation = {} # complicated slightly optimized
+            # for p in prototypes:
+            #     dbfn = p.getFilename()
+            #     trajType = p.getTrajectoryType()
+            #     if (dbfn, trajType) in loadingInformation:
+            #         loadingInformation[(dbfn, trajType)].append(p)
+            #     else:
+            #         loadingInformation[(dbfn, trajType)] = [p]
+            # for k, v in loadingInformation.iteritems():
+            #     objects += loadTrajectoriesFromSqlite(k[0], k[1], [p.getNum() for p in v])
     except sqlite3.OperationalError as error:
         printDBError(error)
     connection.close()
-    if len(set(trajectoryTypes)) > 1:
-        print('Different types of prototypes in database ({}).'.format(set(trajectoryTypes)))
-    return prototypeIndices, dbFilenames, trajectoryTypes, nMatchings, objects
+    if len(set([p.getTrajectoryType() for p in prototypes])) > 1:
+        print('Different types of prototypes in database ({}).'.format(set([p.getTrajectoryType() for p in prototypes])))
+    return prototypes
 
 def savePOIs(filename, gmm, gmmType, gmmId):
     '''Saves a Gaussian mixture model (of class sklearn.mixture.GaussianMixture)
--- a/scripts/learn-motion-patterns.py	Wed Jul 05 16:30:04 2017 -0400
+++ b/scripts/learn-motion-patterns.py	Wed Jul 05 18:01:43 2017 -0400
@@ -5,12 +5,13 @@
 #import matplotlib.pyplot as plt
 import numpy as np
 
-import ml, utils, storage
+import ml, utils, storage, moving
 
 parser = argparse.ArgumentParser(description='The program learns prototypes for the motion patterns') #, epilog = ''
 #parser.add_argument('--cfg', dest = 'configFilename', help = 'name of the configuration file')
 parser.add_argument('-d', dest = 'databaseFilename', help = 'name of the Sqlite database file', required = True)
-parser.add_argument('-r', dest = 'initialPrototypeDatabaseFilename', help = 'name of the Sqlite database file for prototypes to start the algorithm with')
+parser.add_argument('-o', dest = 'outputPrototypeDatabaseFilename', help = 'name of the Sqlite database file to save prototypes')
+parser.add_argument('-i', dest = 'inputPrototypeDatabaseFilename', help = 'name of the Sqlite database file for prototypes to start the algorithm with')
 parser.add_argument('-t', dest = 'trajectoryType', help = 'type of trajectories to learn from', choices = ['objectfeatures', 'feature', 'object'], default = 'objectfeatures')
 parser.add_argument('--max-nobjectfeatures', dest = 'maxNObjectFeatures', help = 'maximum number of features per object to load', type = int, default = 1)
 parser.add_argument('-n', dest = 'nTrajectories', help = 'number of the object or feature trajectories to load', type = int, default = None)
@@ -34,7 +35,7 @@
 # 4. load objects from several files, save in another -> see metadata: site with view and times
 # 5. keep prototypes, with positions/velocities, in separate db (keep link to original data through filename, type and index)
 
-# TODO add possibility to cluter with velocities
+# TODO add possibility to clutesr with velocities
 # TODO add possibility to start with saved prototypes so that one can incrementally learn from several databases
 # save the objects that match the prototypes
 # write an assignment function for objects
@@ -54,6 +55,9 @@
 else:
     objects = storage.loadTrajectoriesFromSqlite(args.databaseFilename, trajectoryType, withFeatures = (args.trajectoryType == 'objectfeatures'), objectNumbers = args.nTrajectories, timeStep = args.positionSubsamplingRate)
 
+if args.inputPrototypeDatabaseFilename is not None:
+    prototypeIndices, dbFilenames, trajectoryTypes, nMatchings, prototypes = storage.loadPrototypesFromSqlite(args.inputPrototypeDatabaseFilename, True)
+    
 trajectories = [o.getPositions().asArray().T for o in objects]
 
 lcss = utils.LCSS(metric = args.metric, epsilon = args.epsilon)
@@ -66,8 +70,13 @@
 clusterSizes = ml.computeClusterSizes(labels, prototypeIndices, -1)
 print(clusterSizes)
 
-prototypes = [objects[i] for i in prototypeIndices]
-storage.savePrototypesToSqlite(args.databaseFilename, [p.getNum() for p in prototypes], prototypeType, [clusterSizes[i] for i in prototypeIndices]) # if saving filenames, add for example [objects[i].dbFilename for i in prototypeIndices]
+
+prototypes = [moving.Prototype(objects[i].getNum(), args.databaseFilename, prototypeType, clusterSizes[i]) for i in prototypeIndices]
+if args.outputPrototypeDatabaseFilename is None:
+    outputPrototypeDatabaseFilename = args.databaseFilename
+else:
+    outputPrototypeDatabaseFilename = args.outputPrototypeDatabaseFilename
+storage.savePrototypesToSqlite(outputPrototypeDatabaseFilename, prototypes)
 
 if args.saveSimilarities:
     np.savetxt(utils.removeExtension(args.databaseFilename)+'-prototype-similarities.txt.gz', similarities, '%.4f')