changeset 828:14e4ad7c7420

work on merging data for synchronized views
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 28 Jun 2016 17:18:45 -0400
parents f6d5da619307
children 0ddcc41663f5
files python/metadata.py python/moving.py scripts/merge-features.py scripts/play-synced-videos.py
diffstat 4 files changed, 78 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/python/metadata.py	Tue Jun 28 15:55:56 2016 -0400
+++ b/python/metadata.py	Tue Jun 28 17:18:45 2016 -0400
@@ -4,11 +4,14 @@
 from os import path
 from math import floor
 
+from numpy import zeros
+
 from sqlalchemy import orm, create_engine, Column, Integer, Float, DateTime, String, ForeignKey, Boolean, Interval
 from sqlalchemy.orm import relationship, backref, sessionmaker
 from sqlalchemy.ext.declarative import declarative_base
 
 from utils import datetimeFormat, removeExtension
+from moving import TimeInterval
 
 Base = declarative_base()
 
@@ -35,6 +38,15 @@
     def getFilename(self):
         return self.name
 
+    @staticmethod
+    def getSite(session, siteId):
+        'Returns the site(s) matching the index or the name'
+        if str.isdigit(siteId):
+            return session.query(Site).filter(Site.idx == int(siteId)).all()
+        else:
+            return session.query(Site).filter(Site.description.like('%'+siteId+'%')).all()
+
+    
 class EnvironementalFactors(Base):
     '''Represents any environmental factors that may affect the results, in particular
     * changing weather conditions
@@ -120,7 +132,6 @@
 
     @orm.reconstructor
     def initOnLoad(self):
-        from numpy import zeros
         if self.intrinsicCameraMatrix00 is not None:
             self.intrinsicCameraMatrix = zeros((3,3))
             self.intrinsicCameraMatrix[0,0] = self.intrinsicCameraMatrix00
@@ -231,7 +242,10 @@
         '''startTime is passed as string in utils.datetimeFormat, eg 2011-06-22 10:00:39
         duration is a timedelta object'''
         self.name = name
-        self.startTime = datetime.strptime(startTime, datetimeFormat)
+        if isinstance(startTime, str):
+            self.startTime = datetime.strptime(startTime, datetimeFormat)
+        else:
+            self.startTime = startTime
         self.duration = duration
         self.site = site
         self.cameraView = cameraView
@@ -244,9 +258,16 @@
         else:
             return self.name
 
+    def getTimeInterval(self):
+        return TimeInterval(self.startTime, self.startTime+self.duration)
+        
     def containsInstant(self, instant):
         'instant is a datetime'
         return self.startTime <= instant and self.startTime+self.duration
+
+    def intersection(self, startTime, endTime):
+        'returns the moving.TimeInterval intersection with [startTime, endTime]'
+        return TimeInterval.intersection(self.getTimeInterval(), TimeInterval(startTime, endTime)) 
         
     def getFrameNum(self, instant):
         'Warning, there is no check of correct time units'
--- a/python/moving.py	Tue Jun 28 15:55:56 2016 -0400
+++ b/python/moving.py	Tue Jun 28 17:18:45 2016 -0400
@@ -98,10 +98,11 @@
     '''Temporal interval: set of instants at fixed time step, between first and last, included
     
     For example: based on frame numbers (hence the modified length method)
-    It may be modified directly by setting first and last'''
+    It may be modified directly by setting first and last
+    It also (mostly) works with datetime.datetime'''
 
-    def __init__(self, first=0, last=-1):
-        super(TimeInterval, self).__init__(first, last, False)
+    def __init__(self, first=0, last=-1, revert = False):
+        super(TimeInterval, self).__init__(first, last, revert)
 
     @staticmethod
     def fromInterval(inter):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/merge-features.py	Tue Jun 28 17:18:45 2016 -0400
@@ -0,0 +1,48 @@
+#! /usr/bin/env python
+
+import sys, argparse, os.path
+import cvutils, utils, moving
+from metadata import createDatabase, Site, VideoSequence
+from datetime import datetime, timedelta
+
+parser = argparse.ArgumentParser(description='The program merges feature trajectories recorded from the same site synchronously between start and end time.')
+parser.add_argument('-i', dest = 'metadataFilename', help = 'name of the metadata file', required = True)
+parser.add_argument('-n', dest = 'siteId', help = 'site id or site name', required = True)
+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
+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)')
+
+args = parser.parse_args()
+
+session = createDatabase(args.metadataFilename)
+
+site = Site.getSite(session, args.siteId)
+if site is None:
+    print('Site {} was not found in {}. Exiting'.format(args.siteId, args.metadataFilename))
+    sys.exit()
+else:
+    site = site[0]
+
+startTime = datetime.strptime(args.startTime, utils.datetimeFormat)
+endTime = datetime.strptime(args.endTime, utils.datetimeFormat)
+processInterval = moving.TimeInterval(startTime, endTime)
+videoSequences = session.query(VideoSequence).filter(VideoSequence.site == site).order_by(VideoSequence.startTime.asc()).all() #.order_by(VideoSequence.cameraViewIdx) .filter(VideoSequence.startTime <= startTime)
+#timeIntervals = [v.intersection(startTime, endTime) for v in videoSequences]
+
+cameraViews = set([v.cameraView for v in videoSequences])
+
+videoSequences = {cv: [v for v in videoSequences if v.cameraView == cv] for cv in cameraViews}
+timeIntervals = {}
+for cv in videoSequences:
+    timeIntervals[cv] = moving.TimeInterval.unionIntervals([v.getTimeInterval() for v in videoSequences[cv]])
+
+commonTimeInterval = timeIntervals.values()[0]
+for inter in timeIntervals.values()[1:]:
+    commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, inter)
+commonTimeInterval = moving.TimeInterval.intersection(commonTimeInterval, processInterval)
+
+# 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
+
+# should we save the information of the new "sequence" in the metadata?
+#session.add(VideoSequence('merged', , timedelta(seconds = 31616./30.), laurierSite, laurierCameraViewSpot0))
+
+#session.commit()
--- a/scripts/play-synced-videos.py	Tue Jun 28 15:55:56 2016 -0400
+++ b/scripts/play-synced-videos.py	Tue Jun 28 17:18:45 2016 -0400
@@ -17,14 +17,12 @@
 
 session = createDatabase(args.metadataFilename)
 
-if str.isdigit(args.siteId):
-    site = session.query(Site).filter(Site.idx == int(args.siteId)).first()
-else:
-    site = session.query(Site).filter(Site.description.like('%'+args.siteId+'%')).first()
-
+site = Site.getSite(session, args.siteId)
 if site is None:
     print('Site {} was not found in {}. Exiting'.format(args.siteId, args.metadataFilename))
     sys.exit()
+else:
+    site = site[0]
 
 dirname = os.path.split(args.metadataFilename)[0]