Source code for VideoWriterPlugin

"""
:filename:     VideoWriterPlugin.py
:author:       roar@tordivel.no
:requirements: Scorpion 9.3.0.515 or higher

Scorpion GUI plugin for creating video from single images

::

  1.0.0.2, 11nov2015, RL: modified for autodoc
  1.0.0.1, 07jun2012, roar@tordivel.no:
    created
"""

__version__ = '1.0.0.2'

import os
import datetime
import cv
import arrToNumpy
from Scorpion import RegisterCallback,GetCameraImages,GetImageMatr,PluginChanged,GetStringValue,GetBoolValue,GetControlByHandle,SelectDirectory,SelectTagname

#-----------------------------------------------------------------------------
# VideoWriterPlugin implementation
#-----------------------------------------------------------------------------
[docs]class VideoWriterPlugin(object): """ Scorpion GUI plugin for creating video from single images """ def __init__(self,cntr,name): self.iname=cntr.iname #full path name of control self.name=name #this plugins name self.loading=True #flag to disable control change event while loading self.writer=None #the videowriter object self.filename='' #current filename self.framecnt=0 #number of frames in current video cntr.deleteControls() #delete previous added controls if any HOFFS = 80 #horizontal position of 2'nd controls VOFFS = 22 #vertical spacing y = VOFFS self.gbSetup=cntr.addControl('GroupBox',0,0) self.gbSetup.align=5 self.gbSetup.caption='Video generation' self.lblSource=self.gbSetup.addControl('Label',8,y) self.lblSource.caption='Source' self.cbSource=self.gbSetup.addControl('ComboBox',HOFFS,self.lblSource.top-2) self.cbSource.style=2 self.cbSource.onClick=self.controlChanged self.cbActive=self.gbSetup.addControl('CheckBox',self.cbSource.right+8,self.lblSource.top) self.cbActive.caption='Active' self.cbActive.onClick=self.controlChanged y+=VOFFS self.lblFormat=self.gbSetup.addControl('Label',8,y) self.lblFormat.caption='Video codec' self.cbFormat=self.gbSetup.addControl('ComboBox',HOFFS,self.lblFormat.top-2) self.cbFormat.style=2 #self.cbFormat.items=('Uncompressed','RGB(A)','I420','IYUV','MPEG-1','MPEG-4.2','MPEG-4.3','MPEG-4','H263','H263I','FLV1') #we don't support all self.cbFormat.items=('Uncompressed','RGB(A)','I420','IYUV') #most common avi formats self.cbFormat.itemIndex=2 #most compressing format self.cbFormat.onClick=self.controlChanged self.lblFps=self.gbSetup.addControl('Label',self.cbFormat.right+8,self.lblFormat.top) self.lblFps.caption='Playback framerate [fps]' self.eFps=self.gbSetup.addControl('Edit',self.lblFps.right+8,self.lblFps.top-2) self.eFps.width=self.eFps.height+4 self.eFps.text='5' self.eFps.onChange=self.controlChanged y+=VOFFS self.lblFolder=self.gbSetup.addControl('Label',8,y) self.lblFolder.caption='Folder' self.eFolder=self.gbSetup.addControl('Edit',HOFFS,self.lblFolder.top-2) self.eFolder.right=self.eFps.left self.eFolder.text='Images' self.eFolder.onChange=self.controlChanged self.bFolder=self.gbSetup.addControl('Button',self.eFps.right-self.eFps.height,self.eFolder.top) self.bFolder.width=self.eFps.height self.bFolder.height=self.eFps.height self.bFolder.caption='...' self.bFolder.onClick=self.bFolderClick y+=VOFFS self.lblGuard=self.gbSetup.addControl('Label',8,y) self.lblGuard.caption='Guard' self.eGuard=self.gbSetup.addControl('Edit',HOFFS,self.lblGuard.top-2) self.eGuard.right=self.eFps.left self.eGuard.text='' self.eGuard.onChange=self.controlChanged self.bGuard=self.gbSetup.addControl('Button',self.eFps.right-self.eFps.height,self.eGuard.top) self.bGuard.width=self.eFps.height self.bGuard.height=self.eFps.height self.bGuard.caption='...' self.bGuard.onClick=self.bGuardClick y+=VOFFS self.pState=self.gbSetup.addControl('Panel',8,y+2) self.pState.width=10 self.pState.height=10 self.pState.bevelInner=0 self.pState.bevelOuter=1 self.pState.caption='' self.pState.color='white' self.lblFrameCnt=self.gbSetup.addControl('Label',self.pState.right+8,y) self.lblFrameCnt.caption='-' self.lblFilename=self.gbSetup.addControl('Label',HOFFS,y) self.lblFilename.caption='' self.updateSourceCombo() self.loading=False RegisterCallback('Actions.BeforeStart',self.actionsBeforeStart) RegisterCallback('Actions.AfterStop',self.actionsAfterStop) RegisterCallback('Actions.AfterGrab',self.actionsAfterGrab) RegisterCallback('System.AccessControlChanged',self.systemAccessControlChanged)
[docs] def updateSourceCombo(self): ''' populete list of images in combobox ''' names=[] imgs=GetCameraImages() idx=self.cbSource.itemIndex #selected if imgs.count>0: for i in range(imgs.count): names.append(imgs.get(i).name) self.cbSource.items=tuple(names) self.cbSource.itemIndex=max(0,min(idx,len(names)))
[docs] def getConfig(self): ''' returns plugin configuration as string ''' from SPB import CreateSpb spb=CreateSpb() #create a spb instance, populate with the plugin configuration #and return the xml string spb.setInt('version',1) spb.setInt('source',self.cbSource.itemIndex) spb.setBool('active',self.cbActive.checked) spb.setInt('format',self.cbFormat.itemIndex) spb.setFloat('fps',float(self.eFps.text)) spb.setText('folder',self.eFolder.text) spb.setText('guard',self.eGuard.text) return spb.xml
[docs] def setConfig(self,value): ''' set plugin configuration from the string 'value' ''' self.loading=True from SPB import CreateSpb spb=CreateSpb(value) #extract plugin configuration from the spb object if spb.getInt('version')==1: self.cbSource.itemIndex=spb.getInt('source') self.cbActive.checked=spb.getBool('active') self.cbFormat.itemIndex=spb.getInt('format') self.eFps.text=str(spb.getFloat('fps')) self.eFolder.text=spb.getText('folder') self.eGuard.text=spb.getText('guard') self.loading=False
[docs] def bFolderClick(self,sender,args): ''' show folder selection dialog ''' folder=os.path.join(GetStringValue('System.Profile'),self.eFolder.text) ok,folder=SelectDirectory(folder) if ok:self.eFolder.text=os.path.relpath(folder,GetStringValue('System.Profile'))
[docs] def bGuardClick(self,sender,args): ''' select guard tagname ''' guard=SelectTagname(self.eGuard.text) if guard<>'':self.eGuard.text=guard
[docs] def controlChanged(self,sender,args): ''' notify configuration changed ''' if not self.loading: PluginChanged(self)
[docs] def enableControls(self): ''' enable controls due to operation state ''' running=GetBoolValue('System.Running') service=GetBoolValue('System.Service') or GetBoolValue('System.Settings') self.cbSource.enabled=service and not running self.cbActive.enabled=not running self.cbFormat.enabled=service and not running self.eFps.enabled=service and not running self.eFolder.enabled=not running self.bFolder.enabled=not running self.eGuard.enabled=service and not running self.bGuard.enabled=service and not running
[docs] def systemAccessControlChanged(self,settings,service): ''' update rights ''' self.enableControls()
[docs] def actionsBeforeStart(self): ''' start of video ''' self.gbSetup.enabled=False #enables controls self.framecnt=0 self.lblFrameCnt.caption='-' self.enableControls()
[docs] def actionsAfterStop(self): ''' end of video ''' self.writer=None #closes video and deletes writer self.gbSetup.enabled=True #enables controls self.pState.color='white' #stopped self.enableControls()
[docs] def actionsAfterGrab(self): ''' add image to video ''' def array2cv(a): dtype2depth = { 'uint8': cv.IPL_DEPTH_8U, 'int8': cv.IPL_DEPTH_8S, 'uint16': cv.IPL_DEPTH_16U, 'int16': cv.IPL_DEPTH_16S, 'int32': cv.IPL_DEPTH_32S, 'float32': cv.IPL_DEPTH_32F, 'float64': cv.IPL_DEPTH_64F, } try: nChannels = a.shape[2] except: nChannels = 1 cv_im = cv.CreateImageHeader((a.shape[1],a.shape[0]),dtype2depth[str(a.dtype)],nChannels) cv.SetData(cv_im, a.tostring(),a.dtype.itemsize*nChannels*a.shape[1]) return cv_im if self.cbActive.checked and GetBoolValue('System.Running') and not GetBoolValue('System.CameraSimulation'): if (self.eGuard.text=='') or GetBoolValue(self.eGuard.text): imgname=GetCameraImages().get(self.cbSource.itemIndex).name src=GetImageMatr(imgname) if self.writer==None: try: height,width=src.dim() if self.cbFormat.itemIndex==0: fcc=0 #Uncompressed elif self.cbFormat.itemIndex==1: fcc=cv.CV_FOURCC('D','I','B',' ') #RGB(A) elif self.cbFormat.itemIndex==2: fcc=cv.CV_FOURCC('I','4','2','0') #I420 elif self.cbFormat.itemIndex==3: fcc=cv.CV_FOURCC('I','Y','U','V') #IYUV elif self.cbFormat.itemIndex==4: fcc=cv.CV_FOURCC('P','I','M','1') #MPEG1 elif self.cbFormat.itemIndex==5: fcc=cv.CV_FOURCC('M','P','4','2') #MPEG-4.2 elif self.cbFormat.itemIndex==6: fcc=cv.CV_FOURCC('D','I','V','3') #MPEG-4.3 elif self.cbFormat.itemIndex==7: fcc=cv.CV_FOURCC('D','I','V','X') #MPEG-4 elif self.cbFormat.itemIndex==8: fcc=cv.CV_FOURCC('U','2','6','3') #H263 elif self.cbFormat.itemIndex==9: fcc=cv.CV_FOURCC('I','2','6','3') #H263I elif self.cbFormat.itemIndex==10:fcc=cv.CV_FOURCC('F','L','V','1') #FLV1 else: fcc=-1 #select dialog folder=os.path.join(GetStringValue('System.Profile'),self.eFolder.text) fname='%s_%s.avi'%(imgname,datetime.datetime.now().strftime('%Y%m%d_%H%M%S')) self.filename=os.path.join(folder,fname) if not os.path.exists(folder): os.mkdir(folder) if src.elemtype()=='uint8' and self.cbFormat.itemIndex==8: color=False else: color=True self.writer=cv.CreateVideoWriter(self.filename,fcc,float(self.eFps.text),(width,height),color) self.lblFilename.caption=fname self.pState.color='red' except Exception,msg: print Exception,msg if self.writer: try: np=arrToNumpy.arrToNumpy(src) img=array2cv(np) cv.WriteFrame(self.writer,img) self.framecnt+=1 self.lblFrameCnt.caption=str(self.framecnt) except Exception,msg: print Exception,msg
[docs]def CreatePlugin(hWnd, name=''): ''' Scorpion Plugin Stub - Required ''' cntr=GetControlByHandle(hWnd) return VideoWriterPlugin(cntr,name)