Mercurial Hosting > traffic-intelligence
changeset 805:180b6b0231c0
added saving/loading points of interests
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Thu, 09 Jun 2016 15:36:21 -0400 |
parents | c5f98916297e |
children | c6f497291fd8 4957e32bb659 bb0fad90cc31 |
files | python/metadata.py python/ml.py python/storage.py python/tests/storage.txt scripts/delete-tables.py scripts/learn-poi.py |
diffstat | 6 files changed, 129 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/python/metadata.py Tue May 31 17:07:23 2016 -0400 +++ b/python/metadata.py Thu Jun 09 15:36:21 2016 -0400 @@ -18,12 +18,16 @@ description = Column(String) # longer names, eg intersection of road1 and road2 xcoordinate = Column(Float) # ideally moving.Point, but needs to be ycoordinate = Column(Float) + mapImageFilename = Column(String) # path to filename, relative to site name, ie sitename/mapImageFilename + nUnitsPerPixel = Column(Float) # number of units of distance per pixel in map image - def __init__(self, name, description = "", xcoordinate = None, ycoordinate = None): + def __init__(self, name, description = "", xcoordinate = None, ycoordinate = None, mapImageFilename = None, nUnitsPerPixel = 1.): self.name = name self.description = description self.xcoordinate = xcoordinate self.ycoordinate = ycoordinate + self.mapImageFilename = mapImageFilename + self.nUnitsPerPixel = nUnitsPerPixel def getFilename(self): return self.name
--- a/python/ml.py Tue May 31 17:07:23 2016 -0400 +++ b/python/ml.py Thu Jun 09 15:36:21 2016 -0400 @@ -209,16 +209,16 @@ return clusterSizes # Gaussian Mixture Models -def plotGMMClusters(model, dataset = None, fig = None, colors = utils.colors, nPixelsPerUnit = 1., alpha = 0.3): +def plotGMMClusters(model, dataset = None, fig = None, colors = utils.colors, nUnitsPerPixel = 1., alpha = 0.3): '''plot the ellipse corresponding to the Gaussians and the predicted classes of the instances in the dataset''' if fig is None: fig = plt.figure() labels = model.predict(dataset) - tmpDataset = nPixelsPerUnit*dataset + tmpDataset = dataset/nUnitsPerPixel for i in xrange(model.n_components): - mean = nPixelsPerUnit*model.means_[i] - covariance = nPixelsPerUnit*model.covars_[i] + mean = model.means_[i]/nUnitsPerPixel + covariance = model.covars_[i]/nUnitsPerPixel if dataset is not None: plt.scatter(tmpDataset[labels == i, 0], tmpDataset[labels == i, 1], .8, color=colors[i]) plt.annotate(str(i), xy=(mean[0]+1, mean[1]+1)) @@ -232,3 +232,4 @@ ell.set_clip_box(fig.bbox) ell.set_alpha(alpha) fig.axes[0].add_artist(ell) + return labels
--- a/python/storage.py Tue May 31 17:07:23 2016 -0400 +++ b/python/storage.py Thu Jun 09 15:36:21 2016 -0400 @@ -384,6 +384,8 @@ dropTables(connection, ['interactions', 'indicators']) elif dataType == 'bb': dropTables(connection, ['bounding_boxes']) + elif dataType == 'pois': + dropTables(connection, ['gaussians2d']) else: print('Unknown data type {} to delete from database'.format(dataType)) connection.close() @@ -506,6 +508,71 @@ return boundingBoxes ######################### +# saving and loading for scene interpretation +######################### + +def savePOIs(filename, gmm, gmmType, gmmId): + '''Saves a Gaussian mixture model (of class sklearn.mixture.GMM) + gmmType is a type of GMM, learnt either from beginnings or ends of trajectories''' + connection = sqlite3.connect(filename) + cursor = connection.cursor() + if gmmType not in ['beginning', 'end']: + print('Unknown POI type {}. Exiting'.format(gmmType)) + import sys + sys.exit() + try: + cursor.execute('CREATE TABLE IF NOT EXISTS gaussians2d (id INTEGER, type VARCHAR, x_center REAL, y_center REAL, covar00 REAL, covar01 REAL, covar10 REAL, covar11 REAL, covariance_type VARCHAR, weight, mixture_id INTEGER, PRIMARY KEY(id, mixture_id))') + for i in xrange(gmm.n_components): + cursor.execute('INSERT INTO gaussians2d VALUES({}, \'{}\', {}, {}, {}, {}, {}, {}, \'{}\', {}, {})'.format(i, gmmType, gmm.means_[i][0], gmm.means_[i][1], gmm.covars_[i][0,0], gmm.covars_[i][0,1], gmm.covars_[i][1,0], gmm.covars_[i][1,1], gmm.covariance_type, gmm.weights_[i], gmmId)) + connection.commit() + except sqlite3.OperationalError as error: + printDBError(error) + connection.close() + +def loadPOIs(filename): + 'Loads all 2D Gaussians in the database' + from sklearn import mixture # todo if not avalaible, load data in duck-typed class with same fields + connection = sqlite3.connect(filename) + cursor = connection.cursor() + pois = [] + try: + cursor.execute('SELECT * from gaussians2d') + gmmId = None + gmm = [] + for row in cursor: + if gmmId is None or row[10] != gmmId: + if len(gmm) > 0: + tmp = mixture.GMM(len(gmm), covarianceType) + tmp.means_ = array([gaussian['mean'] for gaussian in gmm]) + tmp.covars_ = array([gaussian['covar'] for gaussian in gmm]) + tmp.weights_ = array([gaussian['weight'] for gaussian in gmm]) + tmp.gmmTypes = [gaussian['type'] for gaussian in gmm] + pois.append(tmp) + gaussian = {'type': row[1], + 'mean': row[2:4], + 'covar': array(row[4:8]).reshape(2,2), + 'weight': row[9]} + gmm = [gaussian] + covarianceType = row[8] + gmmId = row[10] + else: + gmm.append({'type': row[1], + 'mean': row[2:4], + 'covar': array(row[4:8]).reshape(2,2), + 'weight': row[9]}) + if len(gmm) > 0: + tmp = mixture.GMM(len(gmm), covarianceType) + tmp.means_ = array([gaussian['mean'] for gaussian in gmm]) + tmp.covars_ = array([gaussian['covar'] for gaussian in gmm]) + tmp.weights_ = array([gaussian['weight'] for gaussian in gmm]) + tmp.gmmTypes = [gaussian['type'] for gaussian in gmm] + pois.append(tmp) + except sqlite3.OperationalError as error: + printDBError(error) + connection.close() + return pois + +######################### # saving and loading for scene interpretation (Mohamed Gomaa Mohamed's PhD) #########################
--- a/python/tests/storage.txt Tue May 31 17:07:23 2016 -0400 +++ b/python/tests/storage.txt Thu Jun 09 15:36:21 2016 -0400 @@ -75,3 +75,18 @@ '# asdlfjasdlkj0' >>> readline(strio, '%#') 'sadlkfjsdlakjf' + +>>> from sklearn.mixture import GMM +>>> from numpy.random import random_sample +>>> nPoints = 50 +>>> points = random_sample(nPoints*2).reshape(nPoints,2) +>>> gmm = GMM(4, covariance_type = 'full') +>>> tmp = gmm.fit(points) +>>> id = 0 +>>> savePOIs('pois-tmp.sqlite', gmm, 'end', id) +>>> reloadedGmm = loadPOIs('pois-tmp.sqlite') +>>> sum(gmm.predict(points) == reloadedGmm[id].predict(points)) == nPoints +True +>>> reloadedGmm[id].gmmTypes[0] == 'end' +True +>>> remove('pois-tmp.sqlite')
--- a/scripts/delete-tables.py Tue May 31 17:07:23 2016 -0400 +++ b/scripts/delete-tables.py Thu Jun 09 15:36:21 2016 -0400 @@ -8,7 +8,7 @@ parser = argparse.ArgumentParser(description='The program deletes (drops) the tables in the database before saving new results (for objects, tables object_features and objects are dropped; for interactions, the tables interactions and indicators are dropped') #parser.add_argument('configFilename', help = 'name of the configuration file') parser.add_argument('-d', dest = 'databaseFilename', help = 'name of the Sqlite database', required = True) -parser.add_argument('-t', dest = 'dataType', help = 'type of the data to remove', required = True, choices = ['object','interaction', 'bb']) +parser.add_argument('-t', dest = 'dataType', help = 'type of the data to remove', required = True, choices = ['object','interaction', 'bb', 'pois']) args = parser.parse_args() storage.deleteFromSqlite(args.databaseFilename, args.dataType)
--- a/scripts/learn-poi.py Tue May 31 17:07:23 2016 -0400 +++ b/scripts/learn-poi.py Thu Jun 09 15:36:21 2016 -0400 @@ -11,10 +11,11 @@ parser = argparse.ArgumentParser(description='The program learns and displays Gaussians fit to beginnings and ends of object trajectories (based on Mohamed Gomaa Mohamed 2015 PhD). TODO: save the data') parser.add_argument('-d', dest = 'databaseFilename', help = 'name of the Sqlite database file', required = True) parser.add_argument('-t', dest = 'trajectoryType', help = 'type of trajectories to display', choices = ['feature', 'object'], default = 'object') -parser.add_argument('-n', dest = 'nClusters', help = 'number of point clusters', required = True, type = int) +parser.add_argument('-norigins', dest = 'nOriginClusters', help = 'number of clusters for trajectory origins', required = True, type = int) +parser.add_argument('-ndestinations', dest = 'nDestinationClusters', help = 'number of clusters for trajectory destinations (=norigins if not provided)', type = int) parser.add_argument('--covariance-type', dest = 'covarianceType', help = 'type of covariance of Gaussian model', default = "full") parser.add_argument('-w', dest = 'worldImageFilename', help = 'filename of the world image') -parser.add_argument('-u', dest = 'pixelsPerUnit', help = 'number pixels per unit of distance', type = float, default = 1.) +parser.add_argument('-u', dest = 'unitsPerPixel', help = 'number of units of distance per pixel', type = float, default = 1.) args = parser.parse_args() @@ -29,25 +30,37 @@ beginnings = np.array(beginnings) ends = np.array(ends) -gmm = mixture.GMM(n_components=args.nClusters, covariance_type = args.covarianceType) -beginningModel=gmm.fit(beginnings) -gmm = mixture.GMM(n_components=args.nClusters, covariance_type = args.covarianceType) -endModel=gmm.fit(ends) +nDestinationClusters = args.nDestinationClusters +if args.nDestinationClusters is None: + nDestinationClusters = args.nOriginClusters -fig = plt.figure() -if args.worldImageFilename is not None and args.pixelsPerUnit is not None: - img = plt.imread(args.worldImageFilename) - plt.imshow(img) -ml.plotGMMClusters(beginningModel, beginnings, fig, nPixelsPerUnit = args.pixelsPerUnit) -plt.axis('equal') -plt.title('Origins') -print('Origin Clusters:\n{}'.format(ml.computeClusterSizes(beginningModel.predict(beginnings), range(args.nClusters)))) - -fig = plt.figure() -if args.worldImageFilename is not None and args.pixelsPerUnit is not None: - img = plt.imread(args.worldImageFilename) - plt.imshow(img) -ml.plotGMMClusters(endModel, ends, fig, nPixelsPerUnit = args.pixelsPerUnit) -plt.axis('equal') -plt.title('Destinations') -print('Destination Clusters:\n{}'.format(ml.computeClusterSizes(endModel.predict(ends), range(args.nClusters)))) +gmmId=0 +for nClusters, points, gmmType in zip([args.nOriginClusters, nDestinationClusters], + [beginnings, ends], + ['beginning', 'end']): + # estimation + gmm = mixture.GMM(n_components=nClusters, covariance_type = args.covarianceType) + model=gmm.fit(beginnings) + if not model.converged_: + print('Warning: model for '+gmmType+' points did not converge') + # plot + fig = plt.figure() + if args.worldImageFilename is not None and args.unitsPerPixel is not None: + img = plt.imread(args.worldImageFilename) + plt.imshow(img) + labels = ml.plotGMMClusters(model, points, fig, nUnitsPerPixel = args.unitsPerPixel) + plt.axis('image') + plt.title(gmmType) + print(gmmType+' Clusters:\n{}'.format(ml.computeClusterSizes(labels, range(model.n_components)))) + # save + storage.savePOIs(args.databaseFilename, model, gmmType, gmmId) + gmmId += 1 + +# fig = plt.figure() +# if args.worldImageFilename is not None and args.pixelsPerUnit is not None: +# img = plt.imread(args.worldImageFilename) +# plt.imshow(img) +# ml.plotGMMClusters(, , fig, nPixelsPerUnit = args.pixelsPerUnit) +# plt.axis('equal') +# plt.title() +# print('Destination Clusters:\n{}'.format(ml.computeClusterSizes(endModel.predict(ends), range(args.nClusters))))