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()