Mercurial > hg > nsaunier > traffic-intelligence
comparison scripts/merge-features.py @ 830:2a5856961933
first working version of feature merging (works with feature grouping)
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Wed, 29 Jun 2016 17:56:19 -0400 |
| parents | 0ddcc41663f5 |
| children | 7058a40a4bbc |
comparison
equal
deleted
inserted
replaced
| 829:0ddcc41663f5 | 830:2a5856961933 |
|---|---|
| 1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
| 2 | 2 |
| 3 import sys, argparse, os.path | 3 import sys, argparse, os.path, sqlite3 |
| 4 import cvutils, utils, moving | 4 import cvutils, utils, moving, storage |
| 5 from metadata import createDatabase, Site, VideoSequence | 5 from metadata import createDatabase, Site, VideoSequence, CameraView |
| 6 from datetime import datetime, timedelta | 6 from datetime import datetime, timedelta |
| 7 | 7 |
| 8 parser = argparse.ArgumentParser(description='The program merges feature trajectories recorded from the same site synchronously between start and end time.') | 8 parser = argparse.ArgumentParser(description='The program merges feature trajectories recorded from the same site synchronously between start and end time.') |
| 9 parser.add_argument('-i', dest = 'metadataFilename', help = 'name of the metadata file', required = True) | 9 parser.add_argument('-i', dest = 'metadataFilename', help = 'name of the metadata file', required = True) |
| 10 parser.add_argument('-n', dest = 'siteId', help = 'site id or site name', required = True) | 10 parser.add_argument('-n', dest = 'siteId', help = 'site id or site name', required = True) |
| 11 parser.add_argument('--t1', dest = 'startTime', help = 'time to start merging features (format %Y-%m-%d %H:%M:%S, eg 2011-06-22 10:00:39)') # if not provided, take common time interval | 11 parser.add_argument('--start', dest = 'startTime', help = 'time to start merging features (format %Y-%m-%d %H:%M:%S, eg 2011-06-22 10:00:39)') # if not provided, take common time interval |
| 12 parser.add_argument('--t2', dest = 'endTime', help = 'time to stop merging features (format %Y-%m-%d %H:%M:%S, eg 2011-06-22 10:00:39)') | 12 parser.add_argument('--end', dest = 'endTime', help = 'time to stop merging features (format %Y-%m-%d %H:%M:%S, eg 2011-06-22 10:00:39)') |
| 13 parser.add_argument('-o', dest = 'outputDBFilename', help = 'name of the output SQLite file', required = True) | |
| 13 | 14 |
| 14 args = parser.parse_args() | 15 args = parser.parse_args() |
| 15 | 16 |
| 16 session = createDatabase(args.metadataFilename) | 17 session = createDatabase(args.metadataFilename) |
| 17 | 18 |
| 23 site = site[0] | 24 site = site[0] |
| 24 | 25 |
| 25 startTime = datetime.strptime(args.startTime, utils.datetimeFormat) | 26 startTime = datetime.strptime(args.startTime, utils.datetimeFormat) |
| 26 endTime = datetime.strptime(args.endTime, utils.datetimeFormat) | 27 endTime = datetime.strptime(args.endTime, utils.datetimeFormat) |
| 27 processInterval = moving.TimeInterval(startTime, endTime) | 28 processInterval = moving.TimeInterval(startTime, endTime) |
| 28 videoSequences = session.query(VideoSequence).filter(VideoSequence.site == site).order_by(VideoSequence.startTime.asc()).all() #.order_by(VideoSequence.cameraViewIdx) .filter(VideoSequence.startTime <= startTime) | 29 cameraViews = session.query(CameraView).filter(CameraView.site == site) |
| 30 videoSequences = session.query(VideoSequence).order_by(VideoSequence.startTime.asc()).all() #.order_by(VideoSequence.cameraViewIdx) .filter(VideoSequence.startTime <= startTime) | |
| 31 videoSequences = [vs for vs in videoSequences if vs.cameraView in cameraViews] | |
| 29 #timeIntervals = [v.intersection(startTime, endTime) for v in videoSequences] | 32 #timeIntervals = [v.intersection(startTime, endTime) for v in videoSequences] |
| 30 | 33 #cameraViews = set([v.cameraView for v in videoSequences]) |
| 31 cameraViews = set([v.cameraView for v in videoSequences]) | |
| 32 | 34 |
| 33 videoSequences = {cv: [v for v in videoSequences if v.cameraView == cv] for cv in cameraViews} | 35 videoSequences = {cv: [v for v in videoSequences if v.cameraView == cv] for cv in cameraViews} |
| 34 timeIntervals = {} | 36 timeIntervals = {} |
| 35 for cv in videoSequences: | 37 for cv in videoSequences: |
| 36 timeIntervals[cv] = moving.TimeInterval.unionIntervals([v.getTimeInterval() for v in videoSequences[cv]]) | 38 timeIntervals[cv] = moving.TimeInterval.unionIntervals([v.getTimeInterval() for v in videoSequences[cv]]) |
| 37 | 39 |
| 40 # intersection of the time interval (union) for each camera view | |
| 38 commonTimeInterval = timeIntervals.values()[0] | 41 commonTimeInterval = timeIntervals.values()[0] |
| 39 for inter in timeIntervals.values()[1:]: | 42 for inter in timeIntervals.values()[1:]: |
| 40 commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, inter) | 43 commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, inter) |
| 41 commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, processInterval) | 44 commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, processInterval) |
| 42 | 45 |
| 46 if commonTimeInterval.empty(): | |
| 47 print('Empty time interval. Exiting') | |
| 48 sys.exit() | |
| 49 | |
| 43 if len(set([cv.cameraType.frameRate for cv in cameraViews])) > 1: | 50 if len(set([cv.cameraType.frameRate for cv in cameraViews])) > 1: |
| 44 print('Different framerates of the cameras ({}) are not handled yet. Exiting'.format([cv.cameraType.frameRate for cv in cameraViews])) | 51 print('Different framerates of the cameras ({}) are not handled yet. Exiting'.format([cv.cameraType.frameRate for cv in cameraViews])) |
| 52 else: | |
| 53 frameRate = cv.cameraType.frameRate | |
| 45 | 54 |
| 46 for cv, v in videoSequences.iteritems(): | 55 try: |
| 47 | 56 outConnection = sqlite3.connect(args.outputDBFilename) |
| 57 outCursor = outConnection.cursor() | |
| 58 storage.createTrajectoryTable(outCursor, 'positions') | |
| 59 storage.createTrajectoryTable(outCursor, 'velocities') | |
| 60 storage.createFeatureCorrespondenceTable(outCursor) | |
| 61 outConnection.commit() | |
| 62 except sqlite3.OperationalError as error: | |
| 63 storage.printDBError(error) | |
| 64 sys.exit() | |
| 48 | 65 |
| 49 # for all camera view, for all video, select from positions and velocities where frame_number is in the right range and insert in new database | 66 dirname = os.path.split(args.metadataFilename)[0] |
| 67 if len(dirname) == 0: | |
| 68 dirname = '.' | |
| 50 | 69 |
| 51 # should we save the information of the new "sequence" in the metadata? | 70 newTrajectoryId = -1 |
| 52 #session.add(VideoSequence('merged', , timedelta(seconds = 31616./30.), laurierSite, laurierCameraViewSpot0)) | 71 # first frame num is commonTimeInterval |
| 72 for cv, vs in videoSequences.iteritems(): | |
| 73 #return cursor.fetchone()[0] == 1 | |
| 74 for videoSequence in vs: | |
| 75 print videoSequence.name | |
| 76 try: | |
| 77 vsConnection = sqlite3.connect(dirname+os.path.sep+videoSequence.getDatabaseFilename()) | |
| 78 vsCursor = vsConnection.cursor() | |
| 79 if commonTimeInterval.first < videoSequence.startTime: | |
| 80 firstFrameNum = -(videoSequence.startTime-commonTimeInterval.first).seconds*frameRate | |
| 81 else: | |
| 82 firstFrameNum = (commonTimeInterval.first-videoSequence.startTime).seconds*frameRate | |
| 83 lastFrameNum = (commonTimeInterval.last-videoSequence.startTime).seconds*frameRate | |
| 84 # positions table | |
| 85 vsCursor.execute('SELECT * FROM positions WHERE frame_number BETWEEN {} AND {} ORDER BY trajectory_id'.format(firstFrameNum, lastFrameNum)) | |
| 86 featureIdCorrespondences = {} | |
| 87 currentTrajectoryId = -1 | |
| 88 for row in vsCursor: | |
| 89 if row[0] != currentTrajectoryId: | |
| 90 currentTrajectoryId = row[0] | |
| 91 newTrajectoryId += 1 | |
| 92 featureIdCorrespondences[currentTrajectoryId] = newTrajectoryId | |
| 93 outCursor.execute(storage.insertTrajectoryQuery('positions'), (newTrajectoryId, row[1]-firstFrameNum, row[2], row[3])) | |
| 94 # velocities table | |
| 95 vsCursor.execute('SELECT * FROM velocities WHERE frame_number BETWEEN {} AND {} ORDER BY trajectory_id'.format(firstFrameNum, lastFrameNum)) | |
| 96 for row in vsCursor: | |
| 97 outCursor.execute(storage.insertTrajectoryQuery('velocities'), (featureIdCorrespondences[row[0]], row[1]-firstFrameNum, row[2], row[3])) | |
| 98 # saving the id correspondences | |
| 99 for oldId, newId in featureIdCorrespondences.iteritems(): | |
| 100 outCursor.execute("INSERT INTO feature_correspondences (trajectory_id, source_dbname, db_trajectory_id) VALUES ({},\"{}\",{})".format(newId, videoSequence.name, oldId)) | |
| 101 outConnection.commit() | |
| 102 except sqlite3.OperationalError as error: | |
| 103 storage.printDBError(error) | |
| 53 | 104 |
| 54 #session.commit() | 105 # TODO save the information of the new "sequence" in the metadata |
| 106 mergedCameraView = CameraView('merged', None, site, cv.cameraType, None, None) | |
| 107 session.commit() | |
| 108 session.add(VideoSequence('merged', commonTimeInterval.first, commonTimeInterval.last-commonTimeInterval.first, mergedCameraView)) | |
| 109 session.commit() |
