def onBrowseCfgFile(self, event): cfg.cfg_nicknames_to_dicts() answer = self.TopLevelParent.config.wantToSave() # save this config before loading new one? if answer == wx.ID_YES: self.TopLevelParent.config.cfgSaveAs(self) # yes -> save cfg file elif answer == wx.ID_CANCEL: return # cancel -> don't save & don't change cfg else: pass # no -> don't save, load new cfg # ----------------------------------------------------------------------------- select a different config file wildcard = "PySolo Video config file (*.cfg)|*.cfg|" \ "All files (*.*)|*.*" # adding space in here will mess it up! dlg = wx.FileDialog(self, message = "Select Configuration File ...", defaultDir = gbl.cfg_path, wildcard = wildcard, style = (wx.FD_OPEN) ) # load new configuration file if dlg.ShowModal() == wx.ID_OK: # show the file browser window self.filePathName = dlg.GetPath() # get the path from the save dialog else: winsound.Beep(600,200) gbl.statbar.SetStatusText('Config file selection failed in cfgPanel.') return self.changeConfig()
def onChangeCfgFile(self, event): cfg.cfg_nicknames_to_dicts() # save current settings to dictionary # make sure file exists self.filePathName = self.TopLevelParent.config.cfgGetFilePathName( self, possiblePathName=self.pickCFGfile.GetValue()) self.changeConfig() # load the new configuration file
def onSaveCfg(self, event): cfg.cfg_nicknames_to_dicts( ) # -------------------------------------------------- update config dictionary r = self.TopLevelParent.config.cfgSaveAs(self) if r: # TODO: progress indicator of some sort? self.TopLevelParent.SetStatusText('Configuration saved.') else: self.TopLevelParent.SetStatusText('Configuration not saved.') winsound.Beep(600, 200)
def onChangeThumbFPS(self, event): input = gbl.correctType(self.thumbFPS.GetValue(), 'thumb_fps') if not (type(input) == int or type(input) == float): input = gbl.thumb_fps # don't change the value if input wasn't a number self.thumbSize.SetValue(input) gbl.cfg_dict[self.mon_ID]['thumb_fps'] = gbl.thumb_fps = input cfg.cfg_nicknames_to_dicts() self.scrolledThumbs.refreshThumbGrid() # refresh thumbnails self.thumbSize.SetFocus()
def onSaveCfg(self, event): cfg.cfg_nicknames_to_dicts() # save any new settings to dictionary if gbl.mon_ID != 0: cfg.mon_nicknames_to_dicts(gbl.mon_ID) r = self.TopLevelParent.config.cfgSaveAs(self) if r: # TODO: progress indicator of some sort? self.TopLevelParent.SetStatusText('Configuration saved.') winsound.Beep(600,200) else: self.TopLevelParent.SetStatusText('Configuration not saved.') winsound.Beep(600,200)
def onGoToPage( self, page_num ): # --------------------------------------------- for changing pages without an event gbl.statbar.SetStatusText(' ') old_ID = gbl.mon_ID if old_ID != 0: # ------------------------------------------------------------------ leaving a monitor page cfg.mon_nicknames_to_dicts( old_ID) # save any changes made to the monitor self.notebookPages[old_ID].clearVideo() # remove video and timer if old_ID == 0: # ---------------------------------------------------------- leaving the configuration page cfg.cfg_nicknames_to_dicts( ) # save any new changes to config parameters try: # ------ don't know if thumbnails or console are showing self.notebookPages[0].scrolledThumbs.clearThumbGrid( ) # remove all thumbnails, timers, and threads except: pass try: # ------ don't know if thumbnails or console are showing self.notebookPages[0].scrolledThumbs.clearConsoleGrid( ) # remove all thumbnails, timers, and threads except: pass # -------------------------------------------------------------------------------- update to the new page number gbl.mon_ID = page_num if page_num == 0: # -------------------------------------------------------- going to configuration page cfg.cfg_dict_to_nicknames() # load configuration page parameters self.notebookPages[0].fillTable() # update the configuration table self.notebookPages[0].scrolledThumbs.refreshThumbGrid( ) # update and start the thumbnails window # self.notebookPages[0].scrolledThumbs.SetScrollbars(1,1,1,1) # does not restore scrollbars # self.Layout() else: # ---------------------------------------------------------------------- going to a monitor page if gbl.mon_ID != 0: cfg.mon_dict_to_nicknames( ) # update nicknames to values for the selected monitor self.notebookPages[ gbl.mon_ID].previewPanel.parent.refreshVideo() # start video self.notebookPages[0].scrolledThumbs.EnableScrolling(1, 1) self.notebookPages[0].Layout() print('check')
def onAddMonitor( self, event ): # --------------------------------------------------------------- Add monitor """ adds a monitor to the list more than 9 monitors creates issues due to differences between alphabetical and numerical sorting. Avoiding problems by not allowing more than 9 monitors. """ cfg.cfg_nicknames_to_dicts( ) # -------------------------------------------- save current cfg settings if gbl.monitors >= 9: # no more than 9 monitors allowed self.TopLevelParent.SetStatusText( 'Too many monitors. Cannot add another.') winsound.Beep(600, 200) return False # -------------------------------------------------------------------- put new monitor settings in gbl nicknames gbl.cfg_dict.append({}) # add a dictionary to the cfg_dict list cfg.cfg_dict_to_nicknames() gbl.monitors += 1 # increase the number of monitors gbl.mon_ID = gbl.monitors # update the current mon_ID gbl.mon_name = 'Monitor%d' % gbl.mon_ID # update the monitor name # if gbl.source_type == 0: # create new webcam name if this is a webcam # gbl.webcams_inuse.append(gbl.mon_name) # only one webcam is supported, but multiple monitors can use it # gbl.webcams += 1 # gbl.source = 'Webcam%d' % gbl.webcams # gbl.source = 'Webcam1' # only one webcam is supported, but multiple monitors can use it cfg.cfg_nicknames_to_dicts( ) # ---------------------------------- save new configuration settings to cfg_dict cfg.mon_nicknames_to_dicts( gbl.mon_ID ) # ----------------------------------------- apply new monitor settings to cfg_dict # --------------------------------------------------------------------------------- add monitor page to notebook self.parent.addMonitorPage() gbl.mon_ID = gbl.cfg_dict[0]['monitors'] cfg.mon_dict_to_nicknames() self.Parent.notebookPages[0].fillTable( ) # update the configuration table self.scrolledThumbs.refreshThumbGrid() # create the thumbnail window # self.SetSizerAndFit(self.cfgPanelSizer) # self.Layout() gbl.mon_ID = 0
def onChangeCfgFile(self, event): # --------------------------------------- new config file selected by text cfg.cfg_nicknames_to_dicts() answer = self.TopLevelParent.config.wantToSave() # ask about saving configuration if answer == wx.ID_YES: self.TopLevelParent.config.cfgSaveAs(self) # do save elif answer == wx.ID_CANCEL: return # cancel changing cfg file else: pass # proceed without saving self.filePathName = self.TopLevelParent.config.cfgGetFilePathName(self, possiblePathName=self.pickCFGfile.GetValue()) # make sure file exists self.changeConfig()
def onChangeThumbSize(self, event): input = gbl.correctType(self.thumbSize.GetValue(), 'thumb_size') if type(input) != tuple: input = gbl.preview_size self.thumbSize.SetValue(input) gbl.cfg_dict[self.mon_ID]['thumb_size'] = gbl.thumb_size = input # update self & cfg_dict cfg.cfg_nicknames_to_dicts() try: self.scrolledThumbs.thumbPanels[1].monitorPanel self.scrolledThumbs.refreshThumbGrid() # refresh thumbnails except: self.scrolledThumbs.thumbPanels[1].trackedMonitor self.scrolledThumbs[0].refreshConsoleGrid() # refresh consoles self.thumbFPS.SetFocus()
def onSaveCfg(self, event): cfg.cfg_nicknames_to_dicts() # save any new settings to dictionary if gbl.mon_ID != 0: cfg.mon_nicknames_to_dicts( gbl.mon_ID) # save current monitor settings to dictionary r = self.TopLevelParent.config.cfgSaveAs( self) # save the configuration if r: self.pickCFGfile.ChangeValue(r) gbl.shouldSaveCfg = False gbl.statbar.SetStatusText('Configuration saved.') winsound.Beep(300, 200) else: gbl.statbar.SetStatusText('Configuration not saved.') winsound.Beep(600, 200)
def onChangeThumbSize(self, event): gbl.shouldSaveCfg = True input = gbl.correctType(self.thumbSize.GetValue(), 'thumbSize') if type(input) != tuple: input = gbl.preview_size # don't change anything if input was not a tuple self.thumbSize.ChangeValue(str(input)) gbl.cfg_dict[self.mon_ID][ 'thumb_size'] = gbl.thumb_size = input # update self & cfg_dict cfg.cfg_nicknames_to_dicts() for mon_ID in range(1, gbl.monitors + 1): self.scrolledThumbs.thumbPanels[ mon_ID].monitorPanel.panelSize = input self.scrolledThumbs.clearGrid(self.panelType) self.scrolledThumbs.refreshGrid(self.panelType) self.onScreenUpdate(event)
def onRemoveMonitor( self, event ): # ------------------------------------------------------ Remove current monitor if self.monitors < 1: # don't remove the last monitor self.TopLevelParent.SetStatusText('Cannot remove last monitor.') winsound.Beep(600, 200) return False old_mon = self.mon_ID # keep track of monitor to be removed gbl.cfg_dict.pop( old_mon ) # delete monitor from dictionary; renumbers list automatically # if self.source[0:6] == 'Webcam': # if needed change global copy of number of webcams # gbl.webcams -= 1 # change number of webcams # gbl.webcams_inuse.remove(self.mon_name) # remove name from webcam list # ------------------------------------------------------------------------ reset higher numbered monitors' names for mon_count in range(old_mon, self.monitors): gbl.cfg_dict[mon_count]['mon_name'] = 'Monitor%d' % ( mon_count) # change monitor names # if gbl.cfg_dict[mon_count]['source'][0:6] == 'Webcam': # gbl.cfg_dict[mon_count]['source'][0:6] = 'Webcam%d' % mon_count # rename webcam -> only 1 webcam currently supported gbl.monitors -= 1 # ------------------------------------------------------ Change global settings if old_mon > gbl.monitors: # change current monitor number only if last monitor was deleted self.mon_ID = old_mon - 1 gbl.mon_ID = self.mon_ID cfg.cfg_nicknames_to_dicts( ) # -------------------------- update config dictionary to change # of monitors cfg.mon_dict_to_nicknames( ) # ------------------------------------------------- get new monitor settings self.parent.repaginate( ) # this will delete the notebook pages and recreate the notebook
def onBrowseCfgFile(self, event): cfg.cfg_nicknames_to_dicts() # save current settings to dictionary # ----------------------------------------------------------------------------- select a different config file wildcard = "PySolo Video config file (*.cfg)|*.cfg|" \ "All files (*.*)|*.*" # adding space in here will mess it up! dlg = wx.FileDialog(self, message="Select Configuration File ...", defaultDir=gbl.cfg_path, wildcard=wildcard, style=(wx.FD_OPEN)) # load new configuration file if dlg.ShowModal() == wx.ID_OK: # show the file browser window self.filePathName = dlg.GetPath( ) # get the path from the save dialog else: winsound.Beep(600, 200) gbl.statbar.SetStatusText( 'Configuration file selection failed in cfgPanel.') return self.changeConfig() # load the new configuration file
def PlayMonitor(self_MP): # ------------------------------------------------------------------------------------------ prepare for capture # ----- use the sourcetype to create the correct type of object for capture """if gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 0: # !!!!! NOT USED because webcams have no end gbl.statbar.SetStatusText('Webcam not available.') winsound.Beep(600, 200) return # ------------------------- to restore webcam delete notification to user and uncomment next line self_MP.captureVideo = realCam(self_MP.mon_ID, self_MP.fps, devnum=0)""" if gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 1: # video file self_MP.captureVideo = virtualCamMovie(self_MP.mon_ID, self_MP.fps, self_MP.source, loop=self_MP.loop) elif gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 2: # folder of images self_MP.captureVideo = virtualCamFrames(self_MP.mon_ID, self_MP.fps, self_MP.source, loop=self_MP.loop) # ------ get actual frame size self_MP.initialSize = (self_MP.initialCols, self_MP.initialRows) = self_MP.captureVideo.initialSize # ------ if panel size desired is bigger than input size if self_MP.panelSize > self_MP.captureVideo.initialSize: winsound.Beep(600, 200) gbl.statbar.SetStatusText('Input frame size is only ' + str(self_MP.initialSize)) self_MP.panelSize = self_MP.captureVideo.initialSize # reduce it to the input size if self_MP.panelType == 'thumb': gbl.thumb_size = self_MP.panelSize elif self_MP.panelType == 'preview': gbl.preview_size = self_MP.panelSize cfg.cfg_nicknames_to_dicts() self_MP.SetSize(self_MP.panelSize) # set panel size to fit desired frame size # ------ handle no source if self_MP.source == None: # make a blank frame npsize = (self_MP.panelSize[1], self_MP.panelSize[0]) # opencv and np use opposite order self_MP.initialSize = self_MP.panelSize oneDframe = np.ones(npsize, np.uint8) self_MP.frame = np.dstack((oneDframe, oneDframe, oneDframe)) # binary frame for creating mask else: # ------ each of the 3 video input classes has a "getImage" function self_MP.frame = self_MP.captureVideo.getImage() try: self_MP.rois # if there are no ROIs yet, make an empty list except: self_MP.rois = self_MP.loadROIsfromMaskFile() # try to load from maskfile # ------------------------------------------------------------------ create masks for overlaying ROIs onto image # ROI frame will zero out masked area and RGBmask will fill in masked area with color self_MP.ROIframe, self_MP.RGBmask = self_MP.makeMaskFrames(self_MP.rois, self_MP.initialSize, self_MP.preview_font, self_MP.preview_RGBcolor, self_MP.line_thickness) # ----------------------------------------- multiply element by element to leave zeros where lines will be drawn self_MP.frame2 = np.multiply(self_MP.frame.copy(), self_MP.ROIframe) # ---------------------------------------------------------------------- add RGBmask to frame to color the lines self_MP.frame3 = np.add(self_MP.frame2.copy(), self_MP.RGBmask) # ---------------------------------------------------------------------------- resize the image to fit the panel self_MP.newframe = cv2.resize(self_MP.frame3.copy(), dsize=self_MP.panelSize) # ------------------------------------------------------------------------------ create bitmap from masked image self_MP.bmp = wx.BitmapFromBuffer(self_MP.panelSize[0], self_MP.panelSize[1], self_MP.newframe.tostring()) # self_MP.playTimer.Start(self_MP.interval) # timer cannot be started here. must start in main thread self_MP.keepPlaying = True self_MP.Show() # display the image
def __init__(self_MP, parent, mon_ID=gbl.mon_ID, panelType='thumb', loop=True): self_MP.mon_ID = mon_ID self_MP.mon_name = gbl.cfg_dict[self_MP.mon_ID]['mon_name'] self_MP.panelType = panelType # ----------------------------------------------- panel attributes if panelType == 'preview': self_MP.size = gbl.cfg_dict[self_MP.mon_ID]['preview_size'] self_MP.fps = gbl.cfg_dict[self_MP.mon_ID]['preview_fps'] elif panelType == 'thumb': self_MP.size = gbl.cfg_dict[0]['thumb_size'] self_MP.fps = gbl.cfg_dict[0]['thumb_fps'] else: self_MP.size = (320, 240) self_MP.fps = 1 print('Unexpected panel type in class monitorPanel') wx.Panel.__init__(self_MP, parent, id=wx.ID_ANY, size=self_MP.size, name=self_MP.mon_name) self_MP.parent = parent self_MP.loop = loop self_MP.keepPlaying = False # flag to start and stop video playback self_MP.source = gbl.cfg_dict[self_MP.mon_ID][ 'source'] # ----------------------------------- video source self_MP.source_type = gbl.cfg_dict[self_MP.mon_ID]['source_type'] # if self_MP.source_type == 0: # get the device number if the panel source is a webcam # self_MP.source = 0 if gbl.genmaskflag: self_MP.ROIs = self_MP.Parent.ROIs else: self_MP.mask_file = gbl.cfg_dict[self_MP.mon_ID]['mask_file'] try: # ------ mask file may be corrupt self_MP.ROIs = gbl.loadROIsfromMaskFile(self_MP.mask_file) except: self_MP.ROIs = [] self_MP.line_thickness = gbl.cfg_dict[self_MP.mon_ID]['line_thickness'] self_MP.interval = 1000 / self_MP.fps self_MP.widgetMaker( ) # ------------------------------------------ panel widgets and sizers self_MP.sizers() self_MP.SetSize(self_MP.size) self_MP.SetMinSize(self_MP.GetSize()) self_MP.SetBackgroundColour('#A9A9A9') self_MP.allowEditing = False # ---------------------------------------- use the sourcetype to create the correct type of object for capture if gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 0: self_MP.captureVideo = realCam(self_MP.mon_ID, self_MP.fps, devnum=0) elif gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 1: self_MP.captureVideo = virtualCamMovie(self_MP.mon_ID, self_MP.fps, self_MP.source, loop=self_MP.loop) elif gbl.cfg_dict[self_MP.mon_ID]['source_type'] == 2: self_MP.captureVideo = virtualCamFrames(self_MP.mon_ID, self_MP.fps, self_MP.source, loop=self_MP.loop) self_MP.initialSize = ( self_MP.initialCols, self_MP.initialRows ) = self_MP.captureVideo.initialSize # input frame size if self_MP.size > self_MP.captureVideo.initialSize: # if size desired is bigger than input size self_MP.size = self_MP.captureVideo.initialSize # reduce it to the input size if panelType == 'thumb': gbl.thumb_size = self_MP.size elif panelType == 'preview': gbl.preview_size = self_MP.size cfg.cfg_nicknames_to_dicts() self_MP.SetSize(self_MP.size) winsound.Beep(600, 200) gbl.statbar.SetStatusText('Input frame size is only ' + str(self_MP.size)) # mouse coordinates for mask panels only if gbl.mon_ID != 0: self_MP.Bind(wx.EVT_LEFT_UP, self_MP.onLeftUp) # ---------------------------------------------------------------------- create a timer that will play the video self_MP.Bind(wx.EVT_PAINT, self_MP.onPaint) self_MP.Bind(wx.EVT_TIMER, self_MP.onNextFrame) self_MP.playTimer = wx.Timer(self_MP, id=wx.ID_ANY) self_MP.numberOfTimers = gbl.numberOfTimers + 1