Mercurial Hosting > traffic-intelligence
changeset 821:26daf35180ad
finished modification and demo script to replay synchronized video (with same frame rate)
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Wed, 22 Jun 2016 16:36:12 -0400 |
parents | e73e7b644428 |
children | 41558145e131 |
files | python/cvutils.py python/metadata.py scripts/play-synced-video.py scripts/play-video.py |
diffstat | 4 files changed, 80 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/python/cvutils.py Wed Jun 22 15:23:20 2016 -0400 +++ b/python/cvutils.py Wed Jun 22 16:36:12 2016 -0400 @@ -146,8 +146,11 @@ newCameraMatrix[1,2] = newImgSize[1]/2. return cv2.initUndistortRectifyMap(intrinsicCameraMatrix, array(distortionCoefficients), identity(3), newCameraMatrix, newImgSize, cv2.CV_32FC1) - def playVideo(filenames, windowNames = None, firstFrameNum = 0, frameRate = -1, interactive = False, printFrames = True, text = None, rescale = 1., step = 1): + def playVideo(filenames, windowNames = None, firstFrameNums = None, frameRate = -1, interactive = False, printFrames = True, text = None, rescale = 1., step = 1): '''Plays the video(s)''' + if len(filenames) == 0: + print('Empty filename list') + return if windowNames is None: windowNames = ['frame{}'.format(i) for i in xrange(len(filenames))] wait = 5 @@ -162,9 +165,10 @@ if array([cap.isOpened() for cap in captures]).all(): key = -1 ret = True - frameNum = firstFrameNum - for cap in captures: - cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum) + nFramesShown = 0 + if firstFrameNums is not None: + for i in xrange(len(captures)): + captures[i].set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNums[i]) while ret and not quitKey(key): rets = [] images = [] @@ -174,19 +178,18 @@ images.append(img) if array(rets).all(): if printFrames: - print('frame {0}'.format(frameNum)) - #if text is not None: - # cv2.putText(img, text, (10,50), cv2.FONT_HERSHEY_PLAIN, 1, cvRed) - for i in xrange(1, len(filenames)): - cvImshow(windowNames[i], images[i], rescale) - cvImshow(windowNames[0], images[0], rescale) # cv2.imshow('frame', img) + print('frame shown {0}'.format(nFramesShown)) + for i in xrange(len(filenames)): + if text is not None: + cv2.putText(images[i], text, (10,50), cv2.FONT_HERSHEY_PLAIN, 1, cvRed) + cvImshow(windowNames[i], images[i], rescale) # cv2.imshow('frame', img) key = cv2.waitKey(wait) if saveKey(key): cv2.imwrite('image-{}.png'.format(frameNum), img) - frameNum += step + nFramesShown += step if step > 1: - for cap in captures: - cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, frameNum) + for i in xrange(len(captures)): + captures.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNums[i]+nFramesShown) cv2.destroyAllWindows() else: print('Video captures for {} failed'.format(filenames))
--- a/python/metadata.py Wed Jun 22 15:23:20 2016 -0400 +++ b/python/metadata.py Wed Jun 22 16:36:12 2016 -0400 @@ -1,9 +1,10 @@ # from moving import Point -from datetime import datetime +from datetime import datetime, timedelta from os import path +from math import floor -from sqlalchemy import orm, create_engine, Column, Integer, Float, DateTime, String, ForeignKey, Boolean +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 @@ -65,16 +66,18 @@ resX = Column(Integer) resY = Column(Integer) frameRate = Column(Float) + frameRateTimeUnit = Column(String, default = 's') undistort = Column(Boolean) intrinsicCameraMatrixStr = Column(String) distortionCoefficientsStr = Column(String) undistortedImageMultiplication = Column(Float) - def __init__(self, name, resX, resY, frameRate, trackingConfigurationFilename = None, undistort = None, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = None): + def __init__(self, name, resX, resY, frameRate, frameRateTimeUnit = 's', trackingConfigurationFilename = None, undistort = None, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = None): self.name = name self.resX = resX self.resY = resY self.frameRate = frameRate + self.frameRateTimeUnit = frameRateTimeUnit self.undistort = False if trackingConfigurationFilename is not None: @@ -92,7 +95,8 @@ self.undistortedImageMultiplication = undistortedImageMultiplication # populate the db - if self.intrinsicCameraMatrix is not None and self.distortionCoefficients is not None: + if hasattr(self, 'intrinsicCameraMatrix') and self.intrinsicCameraMatrix is not None\ + and hasattr(self, 'distortionCoefficients') and self.distortionCoefficients is not None: self.intrinsicCameraMatrixStr = ' '.join('{}'.format(x) for x in self.intrinsicCameraMatrix.flatten('C')) self.distortionCoefficientsStr = ' '.join('{}'.format(x)for x in self.distortionCoefficients) @@ -107,6 +111,7 @@ class CameraView(Base): __tablename__ = 'camera_views' idx = Column(Integer, primary_key=True) + description = Column(String) homographyFilename = Column(String) # path to homograph filename, relative to the site name siteIdx = Column(Integer, ForeignKey('sites.idx')) cameraTypeIdx = Column(Integer, ForeignKey('camera_types.idx')) @@ -114,9 +119,10 @@ trackingConfigurationFilename = Column(String) # path to configuration .cfg file, relative to site name site = relationship("Site", backref=backref('sites', order_by = idx)) - camera = relationship('CameraType', backref=backref('camera_views', order_by = idx)) + cameraType = relationship('CameraType', backref=backref('camera_views', order_by = idx)) - def __init__(self, homographyFilename, site, cameraType, trackingConfigurationFilename): + def __init__(self, description, homographyFilename, site, cameraType, trackingConfigurationFilename): + self.description = description self.homographyFilename = homographyFilename self.site = site self.cameraType = cameraType @@ -167,8 +173,7 @@ idx = Column(Integer, primary_key=True) name = Column(String) # path relative to the the site name startTime = Column(DateTime) - duration = Column(Float) # video sequence duration - durationUnit = Column(String, default = 's') + duration = Column(Interval) # video sequence duration databaseFilename = Column(String) # path relative to the the site name siteIdx = Column(Integer, ForeignKey('sites.idx')) cameraViewIdx = Column(Integer, ForeignKey('camera_views.idx')) @@ -177,7 +182,8 @@ cameraView = relationship("CameraView", backref=backref('video_sequences', order_by = idx)) def __init__(self, name, startTime, duration, site, cameraView, databaseFilename = None): - 'startTime is passed as string in utils.datetimeFormat, eg 2011-06-22 10:00:39' + '''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) self.duration = duration @@ -192,7 +198,16 @@ else: return self.name - + def containsInstant(self, instant): + 'instant is a datetime' + return self.startTime <= instant and self.startTime+self.duration + + def getFrameNum(self, instant): + 'Warning, there is no check of correct time units' + if self.containsInstant(instant): + return int(floor((instant-self.startTime).seconds*self.cameraView.cameraType.frameRate)) + else: + return None # add class for Analysis: foreign key VideoSequenceId, dataFilename, configFilename (get the one from camera view by default), mask? (no, can be referenced in the tracking cfg file)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/play-synced-video.py Wed Jun 22 16:36:12 2016 -0400 @@ -0,0 +1,37 @@ +#! /usr/bin/env python + +import sys, argparse, os.path +import cvutils, utils +from metadata import createDatabase, Site, VideoSequence +from datetime import datetime, timedelta + +parser = argparse.ArgumentParser(description='The program displays several views of the same site synchronously.') +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('-t', dest = 'startTime', help = 'time to start playing (format %Y-%m-%d %H:%M:%S, eg 2011-06-22 10:00:39)', required = True) +parser.add_argument('--fps', dest = 'frameRate', help = 'approximate frame rate to replay', default = -1, type = float) +parser.add_argument('-r', dest = 'rescale', help = 'rescaling factor for the displayed image', default = 1., type = float) +parser.add_argument('-s', dest = 'step', help = 'display every s image', default = 1, type = int) + +args = parser.parse_args() + +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() + +if site is None: + print('Site {} was not found in {}. Exiting'.format(args.siteId, args.metadataFilename)) + sys.exit() + +dirname = os.path.split(args.metadataFilename)[0] + +startTime = datetime.strptime(args.startTime, utils.datetimeFormat) +videoSequences = session.query(VideoSequence).filter(VideoSequence.site == site).filter(VideoSequence.startTime <= startTime).all() +videoSequences = [v for v in videoSequences if v.containsInstant(startTime)] +filenames = [dirname+os.path.sep+v.getVideoSequenceFilename() for v in videoSequences] +firstFrameNums = [v.getFrameNum(startTime) for v in videoSequences] + +cvutils.playVideo(filenames, [v.cameraView.description for v in videoSequences], firstFrameNums, args.frameRate, rescale = args.rescale, step = args.step)
--- a/scripts/play-video.py Wed Jun 22 15:23:20 2016 -0400 +++ b/scripts/play-video.py Wed Jun 22 16:36:12 2016 -0400 @@ -7,7 +7,7 @@ parser = argparse.ArgumentParser(description='The program displays the video.') parser.add_argument('-i', dest = 'videoFilename', help = 'name of the video file', required = True) parser.add_argument('-f', dest = 'firstFrameNum', help = 'number of first frame number to display', default = 0, type = int) -parser.add_argument('--fps', dest = 'frameRate', help = 'approximate frame rate to replay', type = float) +parser.add_argument('--fps', dest = 'frameRate', help = 'approximate frame rate to replay', default = -1, type = float) parser.add_argument('-r', dest = 'rescale', help = 'rescaling factor for the displayed image', default = 1., type = float) parser.add_argument('-s', dest = 'step', help = 'display every s image', default = 1, type = int) @@ -17,8 +17,4 @@ if args.firstFrameNum is not None: firstFrameNum = args.firstFrameNum -frameRate = -1 -if args.frameRate is not None: - frameRate = args.frameRate - -cvutils.playVideo([args.videoFilename], None, firstFrameNum, frameRate, rescale = args.rescale, step = args.step) +cvutils.playVideo([args.videoFilename], None, [firstFrameNum], args.frameRate, rescale = args.rescale, step = args.step)