def __init__(self, parent=None):
        super(DistancesWindow, self).__init__('Distances', parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        #self.layout().setMargin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._datasets_panel = ControlEmptyWidget('Paths')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._formset = ['_datasets_panel', '_apply', '_progress']

        self.load_order = ['_datasets_panel']

        self.datasets_dialog = DatasetsDialog(self)
        self._datasets_panel.value = self.datasets_dialog
        self.datasets_dialog.datasets_filter = lambda x: isinstance(
            x, (Path, Contours))

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()
    def __init__(self, parent=None):
        super(BackgroundFinderWindow, self).__init__('Background finder',
                                                     parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        self.setMinimumHeight(400)
        self.setMinimumWidth(400)

        self._panel = ControlEmptyWidget('Videos')
        self._image = ControlImage('Image')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._matrixSize = ControlSlider('Gaussian blur matrix size',
                                         default=5,
                                         minimum=1,
                                         maximum=11)
        self._sigmaX = ControlSlider('Gaussian blur sigma X',
                                     default=5,
                                     minimum=1,
                                     maximum=11)

        self._jump_2_frame = ControlSlider('Jump n frames',
                                           default=100,
                                           minimum=1,
                                           maximum=10000)
        self._cmp_jump = ControlSlider('Compare with frame in front',
                                       default=100,
                                       minimum=1,
                                       maximum=10000)
        self._threshold = ControlSlider('Threshold',
                                        default=5,
                                        minimum=0,
                                        maximum=255)

        self._formset = [[
            '_panel',
            '||',
            [
                ('_matrixSize', '_sigmaX'),
                ('_jump_2_frame', '_cmp_jump', '_threshold'),
                '_image',
            ],
        ], '_apply', '_progress']

        self.videos_dialog = VideosDialog(self)
        self._panel.value = self.videos_dialog
        self.videos_dialog.interval_visible = False

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()
예제 #3
0
    def __init__(self, parent=None):
        BaseWidget.__init__(self, 'Motion counter', parent_win=parent)

        self.set_margin(5)

        self.setMinimumHeight(300)
        self.setMinimumWidth(500)

        self._player = ControlPlayer('Player')
        self._datasets = ControlEmptyWidget('Paths', default=DatasetsDialog())
        self._backgrounds = ControlEmptyWidget('Backgrounds',
                                               default=ObjectsDialog())
        self._show_diff = ControlCheckBox('Show diffs boxes')
        self._threshold = ControlSlider('Threshold',
                                        default=5,
                                        minimum=1,
                                        maximum=255)
        self._radius = ControlSlider('Radius',
                                     default=30,
                                     minimum=1,
                                     maximum=200)
        self._apply = ControlButton('Apply', checkable=True)
        self._compare = ControlCombo('Compare with')
        self._progress = ControlProgress('Progress')

        self._formset = [
            '_datasets', '=', '_compare', '_backgrounds',
            ('_threshold', '_radius', '_show_diff'), '_player', '_apply',
            '_progress'
        ]

        self._compare.add_item('Last frame', 1)
        self._compare.add_item('First frame', 2)
        self._compare.add_item('Background image', 3)

        self.load_order = ['_threshold', '_radius', '_show_diff']

        self._backgrounds.value.datasets_filter = lambda x: isinstance(
            x, Image)
        self._datasets.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path))
        self._player.process_frame_event = self.__process_frame_event
        self._datasets.value.video_selection_changed_event = self.__video_selection_changed_event

        self._compare.changed_event = self.__compare_changed_event

        self._apply.value = self.__apply_btn_event
        self._apply.icon = conf.ANNOTATOR_ICON_MOTION

        self._progress.hide()
        self._backgrounds.hide()
예제 #4
0
    def __init__(self):
        super().__init__('Student Info')

        self.set_margin(10)

        self.formset = []

        leftside = []

        leftside.append('Target GPA')
        self.slider = ControlSlider('', 2.5, 1.0, 4.0)
        leftside.append('slider')

        leftside.append('Current Enrollment: ')
        leftside.append(str(len(university.students)))

        leftside.append('Max Enrollment: ')
        leftside.append(str(university.capacity()))

        self.pbar = ControlProgress()
        self.pbar.min = 0
        self.pbar.max = university.capacity()
        self.pbar.value = len(university.students)
        leftside.append('pbar')

        leftside.append('Average GPA: ')
        # need to add grad_rate
        leftside.append('2.3')
        leftside.append('Graduation Rate: ')
        leftside.append(str(university.grad_rate))
        leftside.append('Average Morale: ')

        # need to add morale
        leftside.append('78%')

        # need to add morale to value
        self.morale_pbar = ControlProgress()
        self.morale_pbar.min = 0
        self.morale_pbar.max = 100
        self.morale_pbar.value = 78
        leftside.append('morale_pbar')

        self.mylist = ControlList('Students')
        self.mylist.horizontal_headers = ['Name', 'GPA', 'Morale']

        for student in university.students:
            self.mylist += (student.name, student.gpa, student.morale)

        self.formset.append((leftside, ' ', 'mylist'))
    def __init__(self, parent=None):
        BaseWidget.__init__(self, 'Export data', parent_win=parent)

        self.set_margin(5)
        self.setMinimumHeight(600)
        self.setMinimumWidth(800)

        self._tree = ControlTree('Data')
        self._apply = ControlButton('Apply', checkable=True)
        self._progress = ControlProgress('Progress')
        self._add = ControlButton('Add')
        self._remove = ControlButton('Remove')
        self._export_list = ControlList('Columns to export')

        self._outdir = ControlDir('Output directory')
        self._outfile = ControlText('Output file name')

        self._toggleevts = ControlCheckBox('Split files by events')
        self._splitevents = ControlCheckBoxList('Events')
        self._evtsreload = ControlButton('Reload events')

        self._formset = [[['_add', '_tree'], '||',
                          ['_remove', '_export_list']], '_toggleevts',
                         '_evtsreload', '_splitevents', '_outdir', '_outfile',
                         '_apply', '_progress']

        self._add.value = self.__add_column_event
        self._remove.value = self.__remove_column_event
        self._apply.value = self.__apply_btn_event
        self._evtsreload.value = self.__reload_events
        self._outdir.changed_event = self.__update_outfile_name_event
        self._outfile.changed_event = self.__update_outfile_name_event
        self._toggleevts.changed_event = self.__toggleevents_visibility
        self._splitevents.changed_event = self.__update_outfile_name_event
        self._splitevents.selection_changed_event = self.__update_outfile_name_event

        self._tree.show_header = False
        self._apply.icon = conf.ANNOTATOR_ICON_MOTION
        self._evtsreload.icon = conf.ANNOTATOR_ICON_REFRESH
        self._add.icon = conf.ANNOTATOR_ICON_ADD
        self._remove.icon = conf.ANNOTATOR_ICON_REMOVE

        self._progress.hide()
        self._splitevents.hide()
        self._evtsreload.hide()
        self._apply.enabled = False

        self._properties = []
예제 #6
0
    def __init__(self):
        super(MainWindow, self).__init__('PABLOPOLY')
        print()
        # Setting defaults settings
        self._board = ControlList(label='Tabuleiro')
        self._playDice = ControlButton('Jogar Dado')
        self.mylabel = ControlLabel('One')
        self._teste = ControlWeb()
        self._teste.value = 'https://github.com/UmSenhorQualquer/pyforms'
        self._myMoney = ControlProgress(label='Your Money is on %p%',
                                        default=15,
                                        min=0,
                                        max=100)
        self._informations = ControlLabel(
            'Inital Money: $ 1500,00 | Max Money: $ 10000,00')

        self._board.value = returnBoad()

        self.formset = [
            (('_teste', '=', '_myMoney'), '_playDice'),
            '_informations',
        ]
        print(self.formset)

        self._playDice.value = self.__playDices
예제 #7
0
    def __init__(self, title=''):
        super(BaseApp, self).__init__(title)

        self._progress = ControlProgress('Processing')
        self._boundings = ControlBoundingSlider('Ranges', horizontal=True)

        #Only creates the variable if didn't exists yet.
        if not hasattr(self, '_modules_tabs'): self._modules_tabs = {}

        self.formset = [(' ', 'Frames bounding', ' '), '_boundings',
                        self._modules_tabs, '_progress']

        #Controls organization definition
        self.mainmenu = [{
            'File': [{
                'Open csv file': self.__open_tracking_file
            }, '-', {
                'Export data': self.export_tracking_file
            }, '-', {
                'Exit': exit
            }]
        }]

        self._data = None

        #Events definition
        self._csvParser = CsvParserDialog()
        self._csvParser.load_file_event = self.load_tracking_file
        self._boundings.changed = self.frames_boundings_changed
예제 #8
0
    def __init__(self):
        super(Example1, self).__init__('dir examples')
        self.parent = None
        self._directory = ControlDir('Choose a directory')
        self._file = ControlFile('Choose a file')
        self._filetree = ControlFilesTree('Choose a file')
        self._image = ControlImage('Image')
        self._boundaries = ControlBoundingSlider('Bounding', horizontal=True)
        self._button = ControlButton('Click')

        self._button.value = self.onButtonClick
        # self._directory.value=self.onButtonClick

        self._checkbox = ControlCheckBox('Choose a directory')
        self._checkboxList = ControlCheckBoxList('Choose a file')
        self._player = ControlPlayer('Choose a file')
        self._slider = ControlSlider('Slider')
        self._player.show()
        self._checkboxList.value = [('Item 1', True), ('Item 2', False), ('Item 3', True)]

        self._combobox = ControlCombo('Choose a item')
        self._list = ControlList('List label')
        self._progress = ControlProgress('Progress bar')
        self._visvisVolume = ControlVisVisVolume('Visvis')
        self._timeline = ControlEventTimeline('Timeline')

        self._combobox.add_item('Item 1', 'Value 1')
        self._combobox.add_item('Item 2', 'Value 2')
        self._combobox.add_item('Item 3', 'Value 3')
        self._combobox.add_item('Item 4')

        self._list.value = [('Item1', 'Item2', 'Item3',), ('Item3', 'Item4', 'Item5',)]
        imageWithVolume = np.zeros((100, 100, 100), np.uint8)
        imageWithVolume[30:40, 30:50, :] = 255
        imageWithVolume[30:40, 70:72, :] = 255
        self._visvisVolume.value = imageWithVolume

        self._visvis = ControlVisVis('Visvis')
        values1 = [(i, random.random(), random.random()) for i in range(130)]
        values2 = [(i, random.random(), random.random()) for i in range(130)]
        self._visvis.value = [values1, values2]

        self.formset = [
            '_visvis'
            , '_directory'
            , '_button'
            , '_file'
            , '_boundaries'
            , '_filetree'
            , '_image'
            , '_slider'
            , ('_checkboxList', '_player')
            , ('_checkbox', ' ')
            , ('_combobox', ' ')
            , '_progress'
            , '='
            , ('_visvisVolume', '||', '_list')
            , '_timeline'
        ]
예제 #9
0
파일: pyforms_ui.py 프로젝트: macieyn/ARpi
    def __init__(self, *args, **kwargs):

        #settings.PYFORMS_STYLESHEET = "style.css"

        super().__init__("EKOHEX Loader GUI v1.0 - Maciej Nachtygal")

        # Definition of the forms fields

        self._uC = ControlCombo("Mikrokontroler: ")
        items = ["Wybierz...", "Attiny 10", "Attiny 13", "Attiny 24"]
        for item in items:
            self._uC.add_item(item)
        self._clock = ControlCombo("Ust. zegara: ")
        self._upload = ControlCombo("Częst. wgrywania: ")
        items = [
            "2 kHz", "4 kHz", "8 kHz", "16 kHz", "32 kHz", "93.75 kHz",
            "187 kHz", "375 kHz", "750 kHz", "1500 kHz"
        ]
        for item in items:
            self._upload.add_item(item)

        self._hexfile = ControlFile("Wybierz plik .hex : ")
        self._reapeat = ControlCheckBox("produkcja")
        self._reapeatInput = ControlText("Ilość: ")
        self._reapeatInput.enabled = False
        self.repeatStatus = self._reapeatInput.enabled

        self._progress = ControlProgress()
        self._progress.min = 0
        self._progress.max = 100
        self.progressStatus = 0

        self._startButton = ControlButton("Start")
        self._stopButton = ControlButton("Stop")
        self.stop = False

        self._logBox = ControlTextArea("Log:")
        self._logBox.readonly = True
        self._logBox.autoscroll = True
        self._logBox.value = "Program gotowy do działania!\n"
        self.avrdudeInfo = ""

        # Define the function that will be called when a file is selected
        self._hexfile.changed_event = self.__hexFileSelectionEvent
        self._uC.changed_event = self.__uCSelectionEvent
        self._clock.changed_event = self.__clockSelectionEvent
        self._upload.changed_event = self.__uploadSelectionEvent
        self._reapeat.changed_event = self.__reapeatSelectionEvent
        self._reapeatInput.changed_event = self.__valueUpdateSelectionEvent
        self._startButton.value = self.__startSelectionEvent
        self._stopButton.value = self.__stopSelectionEvent
        # Define the organization of the Form Controls
        self._formset = [("_hexfile"), ("_uC", "_clock"),
                         ("_upload", "_reapeat", "_reapeatInput"),
                         ("_progress"), ("_startButton", "_stopButton"),
                         "_logBox"]
예제 #10
0
	def __init__(self, parent=None):
		BaseWidget.__init__(self, 'Regions filter', parent_win=parent)
		self.mainwindow = parent

		self.set_margin(5)
		
		self.setMinimumHeight(300)
		self.setMinimumWidth(500)

		self._paths = []

		self._pathspanel	= ControlEmptyWidget('Path to process')
		self._geomspanel 	= ControlEmptyWidget('Geometries')		
		self._apply  		= ControlButton('Apply', checkable=True)
		self._progress  	= ControlProgress('Progress')

		
		self._formset = [
			'_pathspanel',
			'_geomspanel',
			'_apply',
			'_progress'
		]

		self.load_order = ['_start', '_end', '_panel']

		self.paths_dialog = DatasetsDialog(self)
		self.paths_dialog.objects_filter  = lambda x: isinstance(x, Object2D)
		self.paths_dialog.datasets_filter = lambda x: isinstance(x, (Contours,Path) )
		self._pathspanel.value = self.paths_dialog

		self.geoms_dialog = ObjectsDialog(self)
		self.geoms_dialog.objects_filter = lambda x: isinstance(x, Geometry)
		self._geomspanel.value = self.geoms_dialog


	
		self._apply.value = self.__apply_btn_event
		self._apply.icon  = conf.ANNOTATOR_ICON_REGIONS

		self._progress.hide()
예제 #11
0
    def __init__(self, parent=None):
        super(SmoothPathsWindow, self).__init__('Smooth paths',
                                                parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._datasets_panel = ControlEmptyWidget('Paths')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._winsize = ControlSlider('Window size',
                                      minimum=3,
                                      default=3,
                                      maximum=100)
        self._order = ControlSlider('Order', minimum=0, default=0, maximum=10)
        self._deriv = ControlSlider('Derivative',
                                    minimum=0,
                                    default=0,
                                    maximum=10)
        self._rate = ControlSlider('Rate', minimum=0, default=0, maximum=10)

        self._formset = [
            '_datasets_panel', '=', '_winsize', '_order', '_deriv', '_rate',
            ' ', '_apply', '_progress'
        ]

        self.load_order = ['_datasets_panel']

        self.datasets_dialog = DatasetsDialog(self)
        self._datasets_panel.value = self.datasets_dialog
        self.datasets_dialog.datasets_filter = lambda x: isinstance(
            x, (Path, Value))

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()
예제 #12
0
    def __init__(self, parent=None):
        super(FindOrientationWindow,
              self).__init__('Estimate countour orientation',
                             parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        self.setMinimumHeight(300)
        self.setMinimumWidth(300)

        self._panel = ControlEmptyWidget('Videos')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)
        self._debug = ControlCheckBox('Create all the intermediate values')

        self._min_steps = ControlSlider('Minimum steps',
                                        default=20,
                                        minimum=1,
                                        maximum=1000)
        self._min_dist = ControlSlider('Minimum distance',
                                       default=30,
                                       minimum=1,
                                       maximum=1000)

        self._panel.value = self.contours_dialog = DatasetsDialog(self)
        self.contours_dialog.datasets_filter = lambda x: isinstance(
            x, Contours)

        self._formset = [
            '_panel', ('_min_steps', '_min_dist'), '_debug', '_apply',
            '_progress'
        ]

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()
예제 #13
0
    def __init__(self, parent=None, parent_win=None):
        BaseWidget.__init__(self, 'Events stats', parent_win=parent_win)
        self._parent = parent

        self._bounds = ControlBoundingSlider('Frames range',
                                             1,
                                             100,
                                             horizontal=True)
        self._nframes = ControlNumber('Merge in a group of', 1800)
        self._videofsp = ControlNumber('FPS', 30.0)
        self._analyseButton = ControlButton('Calculate graphs')
        self._events = ControlCheckBoxList()
        self._graph = ControlVisVis('Graph')
        self._showTotalCounts = ControlCheckBox('Show total events counting')
        self._showEvtsCounts = ControlCheckBox('Show events counting', True)
        self._progress = ControlProgress()
        self._exportDurations = ControlButton('Export durations')
        self._exportTotals = ControlButton('Export totals')

        self._formset = [(' ', '_showEvtsCounts', '|', '_showTotalCounts', '|',
                          '_nframes', '_videofsp', '_analyseButton',
                          '_exportDurations', '_exportTotals'), '_bounds', {
                              'a:Graph': ['_graph'],
                              'c:Events selection': ['_events']
                          }, '_progress']

        self._analyseButton.value = self.__generate_graph
        self._exportDurations.value = self.__export_durations
        self._exportTotals.value = self.__export_totals
        self._progress.hide()

        self.__load_events()

        self.set_margin(5)

        self.setMinimumWidth(800)
        self.setMinimumHeight(600)
예제 #14
0
 def __init__(self, *args, **kwargs):
     super().__init__('Youtube Downloader')
     self._url = ControlText('Link')
     self._runbutton = ControlButton('Download')
     self._progress = ControlProgress(max=100)
     self._actualLabel = ControlLabel("Progess:")
     self._status = ControlLabel("Idle")
     self._eta = ControlLabel("")
     self.pattern = re.compile(
         r"^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$")
     # self._thumbnail = ControlImage()
     self._formset = [('_url', '_runbutton'), ('_actualLabel', '_status'),
                      ('_progress', '_eta'), ' ']
     # self._url.finishEditing = self.__downloadImage
     self._runbutton.value = self.__buttonAction
     self.disabled = False
예제 #15
0
    def __init__(self, *args, **kwargs):
        super().__init__('Computer vision algorithm example')

        self.set_margin(10)

        #Definition of the forms fields

        self._indir = ControlText(label="Choose Dir:", value=self.INDIR)
        self._indir.value = self.INDIR

        self._outdir = ControlText(label="Choose Output Dir:",
                                   value=self.OUTDIR)
        self._outdir.value = self.OUTDIR

        self._infiles = []
        self._filescount = ControlLabel("Total Files Selected: ")

        self._selectfiles = ControlButton('Select Files')
        self._selectfiles.value = self.__loadFiles

        # self._videofile  = ControlFile('Video')
        # self._outputfile = ControlText('Results output file')
        # self._threshold  = ControlSlider('Threshold', default=114, minimum=0, maximum=255)
        # self._blobsize   = ControlSlider('Minimum blob size', default=110, minimum=100, maximum=2000)
        # self._player     = ControlPlayer('Player')
        self._runbutton = ControlButton('Run')

        # #Define the function that will be called when a file is selected
        # self._videofile.changed_event     = self.__videoFileSelectionEvent
        # #Define the event that will be called when the run button is processed
        self._runbutton.value = self.__runEvent

        self._progress_label = ControlLabel("Progress:")
        self._progress = ControlProgress("%")
        # #Define the event called before showing the image in the player
        # self._player.process_frame_event    = self.__process_frame

        self._image_tbls = controls.ControlList()

        #Define the organization of the Form Controls
        self._formset = [('_indir', '_outdir'),
                         ('_filescount', '_selectfiles'), '_image_tbls',
                         '_runbutton', ('_progress_label', '_progress'), '']
예제 #16
0
class Stats(BaseWidget):
    def __init__(self, parent=None, parent_win=None):
        BaseWidget.__init__(self, 'Events stats', parent_win=parent_win)
        self._parent = parent

        self._bounds = ControlBoundingSlider('Frames range',
                                             1,
                                             100,
                                             horizontal=True)
        self._nframes = ControlNumber('Merge in a group of', 1800)
        self._videofsp = ControlNumber('FPS', 30.0)
        self._analyseButton = ControlButton('Calculate graphs')
        self._events = ControlCheckBoxList()
        self._graph = ControlVisVis('Graph')
        self._showTotalCounts = ControlCheckBox('Show total events counting')
        self._showEvtsCounts = ControlCheckBox('Show events counting', True)
        self._progress = ControlProgress()
        self._exportDurations = ControlButton('Export durations')
        self._exportTotals = ControlButton('Export totals')

        self._formset = [(' ', '_showEvtsCounts', '|', '_showTotalCounts', '|',
                          '_nframes', '_videofsp', '_analyseButton',
                          '_exportDurations', '_exportTotals'), '_bounds', {
                              'a:Graph': ['_graph'],
                              'c:Events selection': ['_events']
                          }, '_progress']

        self._analyseButton.value = self.__generate_graph
        self._exportDurations.value = self.__export_durations
        self._exportTotals.value = self.__export_totals
        self._progress.hide()

        self.__load_events()

        self.set_margin(5)

        self.setMinimumWidth(800)
        self.setMinimumHeight(600)

    def __load_events(self):
        """
		This function load the events present in the main window
		"""
        self._events_list = []

        event_types = []
        start = None
        end = None
        for track in self._parent.tracks:
            for delta in track.events:
                if delta.title not in event_types:
                    self._events += (delta.title, True)
                    event_types.append(delta.title)

                if start == None or start > delta._begin:
                    start = delta._begin
                if end == None or end < delta._end:
                    end = delta._end

                self._events_list.append(
                    (delta._begin, delta._end, delta.title))

        if len(self._events_list) == 0:
            return

        self._events_list = sorted(self._events_list,
                                   key=lambda x: (x[1], x[0]))

        # Set the bounding bar for the frames selection
        self._bounds.min = start - 10
        self._bounds.max = end + 10
        self._bounds.value = (start, end)
        self._nframes.min = 1
        self._nframes.max = end

        self.__generate_graph()

    def __do_the_calculations(self):
        self._values2display = []
        self._legends = []
        self._duration = {}

        events_to_include = self._events.value

        # If no events are selected, clean the graph and exit the function
        if len(events_to_include) == 0 or \
          (not self._showTotalCounts.value and not self._showEvtsCounts.value):
            return

        self._progress.min = 0
        self._progress.max = self._bounds.value[1]
        self._progress.value = 0
        self._progress.show()

        framesBin = self._nframes.value
        totalFrames = int(self._bounds.value[1] + 1)
        # Stores the counting related to a all the events
        totalcounts = np.array([0 for x in range(totalFrames)])
        # Stores the counting related each event
        counts = {}

        for label in events_to_include:
            counts[label] = np.array([0 for x in range(totalFrames)])
            self._duration[label] = np.array([0 for x in range(totalFrames)])

        for i in range(0, totalFrames):
            # events_counted - this variable is used to
            # avoid repeating the same event in the current BIN counting
            if (i % framesBin) == 0:
                events_counted = []

            self._progress.value = i

            for j, (start, end, event) in enumerate(self._events_list):
                if start <= i and end >= i and \
                  (event in events_to_include) and \
                  (j not in events_counted):  # Do not count again a event that was already counted for this BIN

                    lowerBound = i - (i % framesBin)
                    upperBound = lowerBound + framesBin
                    totalcounts[lowerBound:upperBound] += 1
                    counts[event][lowerBound:upperBound] += 1

                    events_counted.append(j)

                if start <= i and end >= i and (event in events_to_include):
                    self._duration[event][i] += 1

        if self._showTotalCounts.value:
            self._values2display.append(totalcounts)
            self._legends.append('All selected events')

        if self._showEvtsCounts.value:
            for label, values in counts.items():
                self._legends.append(label)
                self._values2display.append(values)

        self._progress.hide()

    def __export_durations(self):
        directory = str(
            QtGui.QFileDialog.getExistingDirectory(
                self, "Select directory to save the data"))
        if directory != '':
            self.__do_the_calculations()

            events_to_include = self._events.value

            self._progress.min = 0
            self._progress.max = self._bounds.value[1] * len(events_to_include)
            self._progress.value = 0
            self._progress.show()

            framesBin = self._nframes.value
            totalFrames = int(self._bounds.value[1] + 1)

            for j, label in enumerate(events_to_include):
                with open(os.path.join(directory, '{0}.csv'.format(label)),
                          'wb') as csvfile:

                    spamwriter = csv.writer(csvfile,
                                            delimiter=' ',
                                            quoting=csv.QUOTE_MINIMAL)
                    spamwriter.writerow([
                        'Period', 'event', 'start frame', 'end frame',
                        'duration in frames', 'duration in seconds'
                    ])
                    for k, i in enumerate(range(0, totalFrames, framesBin)):
                        count = sum(self._duration[label][i:i + framesBin])
                        time = float(count) / float(self._videofsp.value)
                        if count > 0:
                            spamwriter.writerow(
                                [k, label, i, i + framesBin, count, time])
                        self._progress.value = i + self._bounds.value[1] * j

    def __export_totals(self):
        directory = str(
            QtGui.QFileDialog.getExistingDirectory(
                self, "Select directory to save the data"))
        if directory != '':
            self.__do_the_calculations()

            events_to_include = self._events.value
            all_events_ordered_by_time = sorted(self._get_all_events(),
                                                key=lambda x: x._begin)

            # these are special point events to mark experiment start and end
            experiment_start_frame_idx = int(
                all_events_ordered_by_time[0].begin)
            experiment_end_frame_idx = int(
                all_events_ordered_by_time[-1].begin)

            try:
                # these are special point events to mark experiment start and end
                events_to_include.remove(all_events_ordered_by_time[0]._title)
                events_to_include.remove(all_events_ordered_by_time[-1].title)
            except Exception as err:
                print("Warning: {0}".format(str(err)))

            self._progress.min = 0
            self._progress.max = self._bounds.value[1] * len(events_to_include)
            self._progress.value = 0
            self._progress.show()

            framesBin = self._nframes.value  # e.g. 1800 if we want separation in minutes and have 30fps
            totalFrames = int(self._bounds.value[1] + 1)
            # totalFrames = int((experiment_end_time - experiment_start_time) + 1)

            with open(os.path.join(directory, 'totals.csv'), 'wb') as csvfile:
                spamwriter = csv.writer(csvfile,
                                        delimiter=',',
                                        quoting=csv.QUOTE_MINIMAL)

                for j, label in enumerate(events_to_include):
                    spamwriter.writerow([label])
                    spamwriter.writerow(
                        ['Period', ' Duration (s)', ' Total', ' Occurrences'])
                    events_occur = self._find_occurrences(
                        self._duration[label])
                    for k, frame_idx in enumerate(
                            range(experiment_start_frame_idx,
                                  experiment_end_frame_idx, int(framesBin))):

                        groups = self.__event_groups_in_frames_threshold(
                            events_occur, frame_idx, frame_idx + framesBin)
                        groups_count = len(groups)
                        frames_count = sum(
                            self._duration[label][frame_idx:frame_idx +
                                                  framesBin])
                        groups_start_times_str = " ".join([
                            format(((group[0] - experiment_start_frame_idx) /
                                    float(framesBin)), ".2f")
                            for group in groups
                        ])
                        # frames_count = sum(list(len(group) for group in groups))
                        time = float(frames_count) / float(
                            self._videofsp.value)
                        if frames_count > 0:
                            # spamwriter.writerow([k, label, i, i + framesBin, frames_count, "{0:.2f}".format(time), groups_count])
                            # spamwriter.writerow(["{period:6}".format(period=k), "{start_second:11}".format(start_second=groups_start_times), "{start_second:15}".format(start_second=i), "{0:13.2f}".format(time), "{count:12}".format(count=groups_count)])

                            spamwriter.writerow([
                                "{period:6}".format(period=k),
                                "{0:13.2f}".format(time),
                                "{count:6}".format(count=groups_count),
                                "{occur:15}".format(
                                    occur=groups_start_times_str)
                            ])
                        else:
                            # spamwriter.writerow([k, label, i, i + framesBin, 0, 0, 0])
                            # spamwriter.writerow(["{period:6}".format(period=k), "{start_second:11}".format(start_second=groups_start_times), "{start_second:15}".format(start_second=i), "{dur:13.2f}".format(dur=0), "{count:12}".format(count=0)])
                            spamwriter.writerow([
                                "{period:6}".format(period=k),
                                "{dur:13.2f}".format(dur=0),
                                "{count:6}".format(count=0),
                                "{:15}".format("--")
                            ])
                        self._progress.value = frame_idx + self._bounds.value[
                            1] * j

                    spamwriter.writerow([])
                    spamwriter.writerow([])

    def _find_occurrences(self, events):
        """
		Returns list with indexes of where value is equal to 1
		In other words, indexes represent frames that correspond to event occurrences
		:param events: all durations occurrences list
		e.g. [0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0]
		returns [1, 2, 4, 5, 6, 8, 11, 12, 13, 14, 15, 16, 17, 18]
		"""

        return list(k for k, i in enumerate(events) if i)  # all indexes of 1

    def __event_groups_in_frames_threshold(self, events_occur,
                                           frames_threshold_first_index,
                                           frames_threshold_last_index):
        """
		Returns list with events occurrences (groups) starting at frames_threshold_first_index, and before frames_threshold_last_index
		e.g.
		events_occur = [1, 2, 4, 5, 6, 8, 11, 12, 13, 14, 15, 16]
		frames_threshold_first_index = 5
		frames_threshold_last_index = 15
		returns [[8], [11, 12, 13, 14, 15, 16]
		"""
        prev = events_occur[0]
        last = 0
        final = []
        for k, i in enumerate(events_occur):
            if (i - prev) > 1:
                final.append(events_occur[last:k])
                last = k
            prev = i
        final.append(events_occur[last:])

        return list(occur for occur in final
                    if occur[0] >= frames_threshold_first_index
                    and occur[0] < frames_threshold_last_index)

    def __generate_graph(self):
        self.__do_the_calculations()

        self._graph.value = self._values2display
        self._graph.legends = self._legends

    def _get_all_events(self):
        self._time = self._parent
        res = []
        for track in self._time.tracks:
            for delta in track._events:
                res.append(delta)
        return res
예제 #17
0
class MotionCounter(BaseWidget):
    def __init__(self, parent=None):
        BaseWidget.__init__(self, 'Motion counter', parent_win=parent)

        self.set_margin(5)

        self.setMinimumHeight(300)
        self.setMinimumWidth(500)

        self._player = ControlPlayer('Player')
        self._datasets = ControlEmptyWidget('Paths', default=DatasetsDialog())
        self._backgrounds = ControlEmptyWidget('Backgrounds',
                                               default=ObjectsDialog())
        self._show_diff = ControlCheckBox('Show diffs boxes')
        self._threshold = ControlSlider('Threshold',
                                        default=5,
                                        minimum=1,
                                        maximum=255)
        self._radius = ControlSlider('Radius',
                                     default=30,
                                     minimum=1,
                                     maximum=200)
        self._apply = ControlButton('Apply', checkable=True)
        self._compare = ControlCombo('Compare with')
        self._progress = ControlProgress('Progress')

        self._formset = [
            '_datasets', '=', '_compare', '_backgrounds',
            ('_threshold', '_radius', '_show_diff'), '_player', '_apply',
            '_progress'
        ]

        self._compare.add_item('Last frame', 1)
        self._compare.add_item('First frame', 2)
        self._compare.add_item('Background image', 3)

        self.load_order = ['_threshold', '_radius', '_show_diff']

        self._backgrounds.value.datasets_filter = lambda x: isinstance(
            x, Image)
        self._datasets.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path))
        self._player.process_frame_event = self.__process_frame_event
        self._datasets.value.video_selection_changed_event = self.__video_selection_changed_event

        self._compare.changed_event = self.__compare_changed_event

        self._apply.value = self.__apply_btn_event
        self._apply.icon = conf.ANNOTATOR_ICON_MOTION

        self._progress.hide()
        self._backgrounds.hide()

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    def __compare_changed_event(self):
        if self._compare.value == 1:
            self._backgrounds.hide()

        elif self._compare.value == 2:
            self._backgrounds.hide()

        elif self._compare.value == 3:
            self._backgrounds.show()

        self._lastframe = None

    def __video_selection_changed_event(self):
        video = self._datasets.value.selected_video
        if video is not None: self._player.value = video.video_capture

    def __process_frame_event(self, frame):
        index = self._player.video_index - 1
        selected_video = self._datasets.value.selected_video
        radius = self._radius.value
        threshold = self._threshold.value

        show_diff = self._show_diff.value

        compare_with = self._compare.value
        if compare_with == 3 and len(self._backgrounds.value.objects):
            background_img = self._backgrounds.value.objects[0].image
            background_img = cv2.cvtColor(background_img, cv2.COLOR_BGR2GRAY)
        else:
            background_img = None

        for video, (begin,
                    end), datasets in self._datasets.value.selected_data:
            if video != selected_video: continue

            for dataset in datasets:
                pos = dataset.get_position(index)
                if pos is None: continue

                if show_diff:
                    # calculate the cut
                    x, y = pos
                    cutx = int(round(x - radius))
                    cuty = int(round(y - radius))
                    cutxx = int(round(x + radius))
                    cutyy = int(round(y + radius))
                    if cutx < 0:
                        cutx = 0
                    if cutxx > frame.shape[1]:
                        cutxx = frame.shape[1]
                    if cuty < 0:
                        cuty = 0
                    if cutyy > frame.shape[0]:
                        cutyy = frame.shape[0]

                    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

                    small = gray[cuty:cutyy, cutx:cutxx].copy()

                    circular_mask = np.zeros((cutyy - cuty, cutxx - cutx),
                                             dtype=np.uint8)
                    cv2.circle(circular_mask, (cutyy - cuty, cutxx - cutx),
                               radius, 255, -1)

                    small_masked = cv2.bitwise_and(circular_mask, small)

                    if not hasattr(self, '_lastframe') or type(
                            self._lastframe) is not np.ndarray:
                        if self._compare.value == 1 or self._compare.value == 2:
                            self._lastframe = gray
                        elif self._compare.value == 3:
                            self._lastframe = background_img

                    if type(self._lastframe) is np.ndarray:
                        last_masked = cv2.bitwise_and(
                            circular_mask, self._lastframe[cuty:cutyy,
                                                           cutx:cutxx])

                        diff = cv2.absdiff(small_masked, last_masked)

                        cv2.circle(frame, pos, radius, (0, 0, 0), -1)

                        frame[cuty:cutyy, cutx:cutxx] += cv2.merge(
                            (diff, diff, diff))

                    if self._compare.value == 1: self._lastframe = gray
                else:
                    cv2.circle(frame, pos, radius, (0, 0, 255), 2)
        return frame

    def __apply_btn_event(self):

        if self._apply.checked:
            self._datasets.enabled = False
            self._show_diff.enabled = False
            self._threshold.enabled = False
            self._player.enabled = False
            self._radius.enabled = False
            self._player.stop()
            self._apply.label = 'Cancel'

            total_2_analyse = 0
            for video, (begin,
                        end), datasets in self._datasets.value.selected_data:
                total_2_analyse += end - begin + 1

            self._progress.min = 0
            self._progress.max = total_2_analyse
            self._progress.show()

            radius = self._radius.value
            threshold = self._threshold.value

            count = 0
            for video, (begin,
                        end), datasets in self._datasets.value.selected_data:
                begin = int(begin)
                end = int(end) + 1

                capture = cv2.VideoCapture(video.filepath)
                capture.set(cv2.CAP_PROP_POS_FRAMES, begin)

                last_image = [None for x in datasets]

                compare_with = self._compare.value
                if compare_with == 3:
                    if len(self._backgrounds.value.objects):
                        background_img = self._backgrounds.value.objects[
                            0].image
                        background_img = cv2.cvtColor(background_img,
                                                      cv2.COLOR_BGR2GRAY)
                    else:
                        self.critical('No background selected')
                        break
                else:
                    background_img = None

                for index in range(begin, end):
                    res, frame = capture.read()
                    if not res: break
                    if not self._apply.checked: break

                    for dataset_index, dataset in enumerate(datasets):
                        pos = dataset.get_position(index)
                        if pos is None: continue

                        x, y = pos
                        cutx = int(round(x - radius))
                        cuty = int(round(y - radius))
                        cutxx = int(round(x + radius))
                        cutyy = int(round(y + radius))
                        if cutx < 0:
                            cutx = 0
                        if cutxx > frame.shape[1]:
                            cutxx = frame.shape[1]
                        if cuty < 0:
                            cuty = 0
                        if cutyy > frame.shape[0]:
                            cutyy = frame.shape[0]

                        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

                        small = gray[cuty:cutyy, cutx:cutxx].copy()

                        circular_mask = np.zeros((cutyy - cuty, cutxx - cutx),
                                                 dtype=np.uint8)
                        cv2.circle(circular_mask, (cutyy - cuty, cutxx - cutx),
                                   radius, 255, -1)

                        small_masked = cv2.bitwise_and(small, small,
                                                       circular_mask)

                        if type(last_image[dataset_index]) is not np.ndarray:
                            last_image[dataset_index] = small_masked
                            if compare_with == 1 or compare_with == 2:
                                last_image[dataset_index] = gray
                            elif compare_with == 3:
                                last_image[dataset_index] = background_img

                        segment = last_image[dataset_index]
                        last_masked = cv2.bitwise_and(
                            circular_mask, segment[cuty:cutyy, cutx:cutxx])

                        diff = cv2.absdiff(small_masked, last_masked)
                        diff[diff < threshold] = 0
                        diff[diff >= threshold] = 1

                        motion = np.sum(diff)
                        dataset.set_motion(index, motion)

                        if compare_with == 1:
                            last_image[dataset_index] = gray

                    self._progress.value = count
                    count += 1

            self._datasets.enabled = True
            self._show_diff.enabled = True
            self._threshold.enabled = True
            self._player.enabled = True
            self._radius.enabled = True
            self._apply.label = 'Apply'
            self._apply.checked = False
            self._progress.hide()
class DistancesWindow(BaseWidget):
    def __init__(self, parent=None):
        super(DistancesWindow, self).__init__('Distances', parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        #self.layout().setMargin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._datasets_panel = ControlEmptyWidget('Paths')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._formset = ['_datasets_panel', '_apply', '_progress']

        self.load_order = ['_datasets_panel']

        self.datasets_dialog = DatasetsDialog(self)
        self._datasets_panel.value = self.datasets_dialog
        self.datasets_dialog.datasets_filter = lambda x: isinstance(
            x, (Path, Contours))

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    ###########################################################################
    ### PROPERTIES ############################################################
    ###########################################################################

    @property
    def datasets(self):
        return self.datasets_dialog.datasets

    def __apply_event(self):

        if self._apply.checked:

            self._datasets_panel.enabled = False
            self._apply.label = 'Cancel'

            total_2_analyse = 0
            for video, (begin,
                        end), datasets in self.datasets_dialog.selected_data:
                total_2_analyse += (end - begin +
                                    1) * len(datasets) * len(datasets)

            self._progress.min = 0
            self._progress.max = total_2_analyse
            self._progress.show()

            count = 0
            for video, (begin,
                        end), datasets in self.datasets_dialog.selected_data:
                begin = int(begin)
                end = int(end) + 1

                if len(datasets) < 2: continue

                for d1_index in range(len(datasets)):
                    for d2_index in range(len(datasets)):
                        if d1_index == d2_index: break
                        if not self._apply.checked: break

                        set1 = datasets[d1_index]
                        set2 = datasets[d2_index]

                        val = set1.object2d.create_value()
                        val.name = "distance-between ({0}) and ({1})".format(
                            set1.name, set2.name)

                        for index in range(begin, end):
                            if not self._apply.checked: break

                            pos1 = set1.get_position(index)
                            if pos1 is None: continue
                            pos2 = set2.get_position(index)
                            if pos2 is None: continue

                            dist = pts_utils.lin_dist(pos1, pos2)
                            val.set_value(index, dist)

                            self._progress.value = count
                            count += 1

                        count = d1_index * d2_index * (end - begin + 1)

            self._datasets_panel.enabled = True
            self._apply.label = 'Apply'
            self._apply.checked = False
            self._progress.hide()
class BackgroundFinderWindow(BaseWidget):
    def __init__(self, parent=None):
        super(BackgroundFinderWindow, self).__init__('Background finder',
                                                     parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        self.setMinimumHeight(400)
        self.setMinimumWidth(400)

        self._panel = ControlEmptyWidget('Videos')
        self._image = ControlImage('Image')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._matrixSize = ControlSlider('Gaussian blur matrix size',
                                         default=5,
                                         minimum=1,
                                         maximum=11)
        self._sigmaX = ControlSlider('Gaussian blur sigma X',
                                     default=5,
                                     minimum=1,
                                     maximum=11)

        self._jump_2_frame = ControlSlider('Jump n frames',
                                           default=100,
                                           minimum=1,
                                           maximum=10000)
        self._cmp_jump = ControlSlider('Compare with frame in front',
                                       default=100,
                                       minimum=1,
                                       maximum=10000)
        self._threshold = ControlSlider('Threshold',
                                        default=5,
                                        minimum=0,
                                        maximum=255)

        self._formset = [[
            '_panel',
            '||',
            [
                ('_matrixSize', '_sigmaX'),
                ('_jump_2_frame', '_cmp_jump', '_threshold'),
                '_image',
            ],
        ], '_apply', '_progress']

        self.videos_dialog = VideosDialog(self)
        self._panel.value = self.videos_dialog
        self.videos_dialog.interval_visible = False

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()

    def init_form(self):
        super(BackgroundFinderWindow, self).init_form()
        self.videos_dialog.project = self.mainwindow.project

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    ###########################################################################
    ### PROPERTIES ############################################################
    ###########################################################################

    def __update_image_event(self, frame, frame_count):
        self._image.value = frame
        self._progress.value = self._base_nframes + frame_count

    def __apply_event(self):

        if self._apply.checked and self._apply.label == 'Apply':
            self._panel.enabled = False
            self._image.enabled = False
            self._matrixSize.enabled = False
            self._sigmaX.enabled = False
            self._jump_2_frame.enabled = False
            self._cmp_jump.enabled = False
            self._threshold.enabled = False

            self._apply.label = 'Cancel'

            total_steps = 0
            for video, _ in self.videos_dialog.selected_data:
                total_steps += video.total_frames

            self._progress.min = 0
            self._progress.max = total_steps
            self._progress.show()

            self._base_nframes = 0
            exit = True
            for video, _ in self.videos_dialog.selected_data:

                if not self._apply.checked: break

                bg = BackgroundDetector(
                    capture=video.video_capture,
                    gaussianBlurMatrixSize=self._matrixSize.value,
                    gaussianBlursigmaX=self._sigmaX.value,
                    update_function=self.__update_image_event)

                bg.detect(self._jump_2_frame.value, self._cmp_jump.value,
                          self._threshold.value)
                image = video.create_image()
                image.name = 'background-{0}'.format(len(list(video.images)))
                image.image = bg.background_color

                self._base_nframes += video.total_frames

            self._panel.enabled = True
            self._image.enabled = True
            self._matrixSize.enabled = True
            self._sigmaX.enabled = True
            self._jump_2_frame.enabled = True
            self._cmp_jump.enabled = True
            self._threshold.enabled = True
            self._apply.label = 'Apply'
            exit = self._apply.checked
            self._apply.checked = False
            self._progress.hide()
예제 #20
0
class RegionsFilter(BaseWidget):

	def __init__(self, parent=None):
		BaseWidget.__init__(self, 'Regions filter', parent_win=parent)
		self.mainwindow = parent

		self.set_margin(5)
		
		self.setMinimumHeight(300)
		self.setMinimumWidth(500)

		self._paths = []

		self._pathspanel	= ControlEmptyWidget('Path to process')
		self._geomspanel 	= ControlEmptyWidget('Geometries')		
		self._apply  		= ControlButton('Apply', checkable=True)
		self._progress  	= ControlProgress('Progress')

		
		self._formset = [
			'_pathspanel',
			'_geomspanel',
			'_apply',
			'_progress'
		]

		self.load_order = ['_start', '_end', '_panel']

		self.paths_dialog = DatasetsDialog(self)
		self.paths_dialog.objects_filter  = lambda x: isinstance(x, Object2D)
		self.paths_dialog.datasets_filter = lambda x: isinstance(x, (Contours,Path) )
		self._pathspanel.value = self.paths_dialog

		self.geoms_dialog = ObjectsDialog(self)
		self.geoms_dialog.objects_filter = lambda x: isinstance(x, Geometry)
		self._geomspanel.value = self.geoms_dialog


	
		self._apply.value = self.__apply_btn_event
		self._apply.icon  = conf.ANNOTATOR_ICON_REGIONS

		self._progress.hide()

	def __reload_tracks_event(self):
		self._tracks.clearItems()
		for track in self.mainwindow._time.tracks:
			self._tracks.addItem(str(track.title), track)
	
	def __apply_btn_event(self):

		if self._apply.checked:
			self._pathspanel.enabled	= False
			self._geomspanel.enabled 	= False
			self._apply.label 			= 'Cancel'

			# calculate the total number of frames to analyse
			total_2_analyse  = 0
			for video, (begin, end), datasets_list in self.paths_dialog.selected_data:
				total_2_analyse += end-begin+1

			self._progress.min = 0
			self._progress.max = total_2_analyse
			self._progress.show()

			contours = []
			for video, geometries in self.geoms_dialog.selected_data:
				for geometry_object in geometries:
					for contour in geometry_object.geometry:
						contours.append(np.int32(contour[1]))

			count = 0
			for video, (begin, end), datasets_list in self.paths_dialog.selected_data:
				begin, end = int(begin), int(end)+1

				for path_dataset in datasets_list:
					object2d  = path_dataset.object2d
					value_obj = object2d.create_value()
					value_obj.name = 'regions-filter ({0})'.format(len(object2d))
					for index in range(begin, end+1):
						pt = path_dataset.get_position(index)
						for contour in contours:
							dist = cv2.pointPolygonTest(contour, pt, True)
							value_obj.set_value(index, dist)
						count += 1
						self._progress.value = count

			self._pathspanel.enabled	= True
			self._geomspanel.enabled 	= True
			self._apply.label 			= 'Apply'
			self._progress.hide()

	
	def add_event_2_timeline(self, track, evt_name, begin, end):
		self.mainwindow.add_event_2_timeline(track, evt_name, begin, end)
	

	def add_dataset_event(self, dataset):
		if isinstance(dataset, Path): self._paths += [dataset, True]

	def removed_dataset_event(self, dataset):
		if isinstance(dataset, Path): self._paths -= dataset

	def removed_object_event(self, obj):
		items2remove = []
		for i, (item, checked) in enumerate(self._paths.items):
			if item.object2d==obj: items2remove.append(i)
		for i in sorted(items2remove,reverse=True): self._paths -= i


	###########################################################################
	### PROPERTIES ############################################################
	###########################################################################

	@property
	def video_filename(self): return None
	@video_filename.setter
	def video_filename(self, value): 
		self._panel.value.video_filename = value
		self._start.max 	= self._panel.value.total_n_frames
		self._end.max 		= self._panel.value.total_n_frames
		

	@property
	def paths(self): return self._paths.value
	@paths.setter
	def paths(self, value):  self._paths.value = value

	def save(self, data): return data
	def load(self, data): pass
예제 #21
0
    def __init__(self):
        global conf
        conf += 'pythonvideoannotator.resources'  # Resources can only be loaded after pyqt is running

        super().__init__('Video annotation editor')

        self._project = Project(parent=self)
        Dialog.project = self._project

        self._player = ControlPlayer("Player")
        self._time = ControlEventTimeline('Time')
        self._dock = ControlDockWidget("Timeline",
                                       side='bottom',
                                       order=1,
                                       margin=5)
        self._progress = ControlProgress('Progress', visible=False)

        # define the application toolbar
        self.toolbar = [
            ControlButton('Open',
                          icon=conf.ANNOTATOR_ICON_OPEN,
                          default=self.__open_project_event),
            ControlButton('Save',
                          icon=conf.ANNOTATOR_ICON_SAVE,
                          default=self.__save_project_event)
        ]

        self.formset = ['_player', '_progress']

        self._dock.value = self._time
        self._player.process_frame_event = self.process_frame_event
        self._player.click_event = self.on_player_click_event
        self._player.double_click_event = self.on_player_double_click_event
        self._player.drag_event = self.on_player_drag_event
        self._player.end_drag_event = self.on_player_end_drag_event

        # ignore these controls key release event
        self._time.key_release_event = lambda x: x
        self._player.key_release_event = lambda x: x

        self.load_order = []

        self.mainmenu.insert(
            0, {
                'File': [{
                    'Open': self.__open_project_event,
                    'icon': conf.ANNOTATOR_ICON_OPEN
                }, '-', {
                    'Save': self.__save_project_event,
                    'icon': conf.ANNOTATOR_ICON_SAVE
                }, {
                    'Save as': self.__save_project_as_event,
                    'icon': conf.ANNOTATOR_ICON_SAVE
                }, '-', {
                    'Exit': QApplication.closeAllWindows,
                    'icon': conf.ANNOTATOR_ICON_EXIT
                }]
            })
        self.mainmenu.insert(1, {'Modules': []})
        self.mainmenu.insert(2, {'Windows': []})

        track_user_stats()

        ########################################################################
        ###### CHECK NEW VERSIONS RELEASES #####################################
        ########################################################################
        try:
            versions = pypi_xmlrpc.package_releases('Python-video-annotator')

            if versions is not None:
                new_version = versions[0]
                if float(new_version) > float(__version__):
                    response = self.question(
                        "<h2>New version <b>[{0}]</b> available</h2>"
                        "<p>Do you wish to update the software?</p>"
                        "<p>The software can be updated later by running the next command in the terminal:</p>"
                        "<i>pip install python-video-annotator --force-reinstall</i>"
                        .format(new_version),
                        'New version [{0}]'.format(new_version))

                    if response == 'yes':
                        subprocess.call([
                            sys.executable, "-m", "pip", "install",
                            'python-video-annotator', '--force-reinstall'
                        ])

                        self.message(
                            'The software was updated and this session will be closed. Please execute the software again.',
                            'Restart required')
                        exit()

            else:
                print('Unable to check new versions')

        except Exception as e:
            print('Unable to check new versions:')
예제 #22
0
class VideosExporterGui(BaseWidget, VideosExporterPreview,
                        VideosExporterProcess):
    def __init__(self, parent=None):
        super(VideosExporterGui, self).__init__('Videos exporter',
                                                parent_win=parent)

        self.set_margin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(400)

        self._toolbox = ControlToolBox('Tool')

        self._panel_area = ControlEmptyWidget('Set the object area',
                                              default=DatasetsDialog(self))
        self._panel_colors = ControlEmptyWidget('Set the object color',
                                                default=DatasetsDialog(self))
        self._panel_imgs = ControlEmptyWidget('Set the video background',
                                              default=ImagesDialog(self))

        #### path panel ################################################
        self._panel_path = ControlEmptyWidget('Set the object path',
                                              default=DatasetsDialog(self))
        self._drawpath = ControlCheckBox('Draw paths')
        ################################################################

        #### draw events ###############################################
        self._drawevents = ControlCheckBoxList('Events')
        self._eventstitles = ControlCheckBox('Draw titles')
        self._evtsreload1 = ControlButton('Reload events')
        ################################################################

        #### split by events ###########################################
        self._splitevents = ControlCheckBoxList('Events')
        self._evtsreload2 = ControlButton('Reload events')
        ################################################################

        self._codec = ControlCheckBox('Force AVI')
        self._outdir = ControlDir('Output directory')
        self._outfile = ControlText('Output file name')

        self._player = ControlPlayer('Player')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Export video(s)', checkable=True)
        self._apply.icon = conf.ANNOTATOR_ICON_PATH
        self._apply.enabled = False

        self._usefixedsize = ControlCheckBox('Use a fixed size')
        self._usefixedcolor = ControlCheckBox('Use a fixed color')
        self._radius = ControlSlider('Circle radius',
                                     default=10,
                                     minimum=1,
                                     maximum=300)
        self._color = ControlText('BGR color', default='255,255,255')

        self.formset = [('_toolbox', '||', '_player'), '=', '_outdir',
                        ('_outfile', '_codec'), '_apply', '_progress']

        self._toolbox.value = [
            ('Path', [self._panel_path, self._drawpath]),
            ('Circle (optional)',
             [self._panel_area, (self._usefixedsize, self._radius)]),
            ('Circle color (optional)',
             [self._panel_colors, (self._usefixedcolor, self._color)]),
            ('Background (optional)', [self._panel_imgs]),
            ('Draw events (optional)',
             [self._evtsreload1, self._drawevents, self._eventstitles]),
            ('Split files by events (optional)',
             [self._evtsreload2, self._splitevents]),
        ]

        self._panel_path.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path))
        #self._panel_area.value.datasets_filter   = lambda x: isinstance(x, Value )
        self._panel_colors.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path)) and hasattr(x, 'has_colors_avg'
                                             ) and x.has_colors_avg

        ### Set the controls events #############################################
        self._evtsreload1.value = self.__reload_events
        self._evtsreload2.value = self.__reload_events
        self._outfile.changed_event = self.outputfile_changed_event
        self._usefixedsize.changed_event = self.__usefixedsize_changed_event
        self._usefixedcolor.changed_event = self.__usefixedcolor_changed_event
        self._splitevents.selection_changed_event = self.outputfile_changed_event
        self._panel_path.value.video_selection_changed_event = self.__video_selection_changed_event
        self._codec.changed_event = self.__video_selection_changed_event
        ## function from VideosExporterProcess class
        self._apply.value = self.apply_event
        ## function from VideosExporterPreview class
        self._player.process_frame_event = self.player_processframe_event

        self._evtsreload1.icon = conf.ANNOTATOR_ICON_REFRESH
        self._evtsreload2.icon = conf.ANNOTATOR_ICON_REFRESH

        self._progress.hide()
        self._radius.hide()
        self._color.hide()
        self.__check_areatab_event()

    ###########################################################################
    ### UTILS #################################################################
    ###########################################################################

    def __reload_events(self):
        """
		Find all the events available on the timeline
		"""
        timeline = self.parent().timeline
        rows = timeline.rows

        events = {}
        for row in rows:
            for event in row.events:
                events[event.title] = True

        events = sorted(events.keys())

        loaded_events = dict(self._drawevents.items)
        self._drawevents.value = [(e, loaded_events.get(e, False))
                                  for e in events]

        loaded_events = dict(self._splitevents.items)
        self._splitevents.value = [(e, loaded_events.get(e, False))
                                   for e in events]

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    def show(self):
        """
		Load the events when the window is oppened
		"""
        super(VideosExporterGui, self).show()
        self.__reload_events()

    def __check_areatab_event(self):
        """
		Activate or deactivate the color tab
		"""
        if len(list(self._panel_area.value.datasets)
               ) > 0 or self._usefixedsize.value:
            self._toolbox.set_item_enabled(2, True)
        else:
            self._toolbox.set_item_enabled(2, False)

    def __usefixedcolor_changed_event(self):
        if self._usefixedcolor.value:
            self._color.show()
            self._panel_colors.hide()
        else:
            self._color.hide()
            self._panel_colors.show()

    def __usefixedsize_changed_event(self):
        self.__check_areatab_event()
        if self._usefixedsize.value:
            self._radius.show()
            self._panel_area.hide()
        else:
            self._radius.hide()
            self._panel_area.show()

    def outputfile_changed_event(self):
        """
		Update the output filename
		"""
        filename = self._outfile.value

        video = self._panel_path.value.selected_video
        if video is not None:
            filename = filename if len(filename) > 0 else video.filename
            videofilepath, video_extension = os.path.splitext(video.filename)
            outfilepath, outfile_extension = os.path.splitext(filename)

            names = [outfilepath] if len(outfilepath) > 0 else []

            if '{videoindex}' not in outfilepath: names.append('{videoindex}')
            if len(list(self._splitevents.value)) > 0:
                if '{event}' not in outfilepath: names.append('{event}')
                if '{start}' not in outfilepath: names.append('{start}')
                if '{end}' not in outfilepath: names.append('{end}')

            self._outfile.value = ('-'.join(names) + video_extension)
            self._apply.enabled = True
        else:
            self._apply.enabled = False

    def __video_selection_changed_event(self):
        """
		Activate the video preview
		"""
        video = self._panel_path.value.selected_video
        if video is not None:
            self._player.value = video.video_capture

    def get_object_area(self, path, areas, index):
        try:
            if self._usefixedsize.value:
                area = (self._radius.value**2 * math.pi)
            elif len(areas) > 0:
                a = areas[0]
                if isinstance(a, Value):
                    area = a.get_value(index)
                else:
                    area = a.get_area_value(index)
            else:
                area = path.get_area_value(index)

            return area
        except:
            return None

    def get_object_color(self, path, colors, index):
        try:
            if self._usefixedcolor.value:
                color = tuple(eval(self._color.value))
            elif len(colors) > 0:
                color = colors[0].get_color_avg(index)
            else:
                color = path.get_color_avg(index)
            if color is None: raise Exception()
        except:
            color = 255, 255, 255
        return color
class ContoursImagesWindow(BaseWidget):

    def __init__(self, parent=None):
        super(ContoursImagesWindow, self).__init__('Contour images', parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)
        

        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._contourspanel = ControlEmptyWidget('Contours datasets')
        self._progress      = ControlProgress('Progress', visible=False)       
        self._apply         = ControlButton('Apply', checkable=True)
        self._toolbox       = ControlToolBox('Toolbox')
        self._exportdir     = ControlDir('Export images to folder', default='images-from-contour')
        

        #### mask ######################################################
        self._usemaskimg       = ControlCheckBox('Apply a mask to the image')
        self._usemaskdilate    = ControlCheckBox('Dilate the mask and apply it to the image')
        self._maskdilatesize   = ControlSlider('Dilate size', default=0, minimum=0, maximum=100)
        self._usemaskellipse   = ControlCheckBox('Apply the min. ellipse as a mask to the image')
        self._usemaskcircular  = ControlCheckBox('Apply a circular mask to the image')
        self._maskcircularsize = ControlSlider('Circular radius', default=0, minimum=0, maximum=100)
        self._usemaskrect      = ControlCheckBox('Apply the min. rect as a mask to the image')
        ################################################################

        #### margin ####################################################
        self._margin = ControlSlider('Margin size', default=0, minimum=0, maximum=100)
        ################################################################

        #### imagesize #################################################
        self._imagesize = ControlSlider('Image size', default=0, minimum=0, maximum=400)
        ################################################################

        #### cut #######################################################
        self._usecut = ControlCheckBox('Cut image')
        self._cutx = ControlBoundingSlider('X cut', default=(10,30), minimum=0, maximum=1000)
        self._cuty = ControlBoundingSlider('Y cut', default=(10,30), minimum=0, maximum=1000)
        ################################################################
        

        #### use stretch ###############################################
        self._usestretch = ControlCheckBox('Stretch image')
        ################################################################

        #### filter per events #########################################
        self._eventslst  = ControlCheckBoxList('Events', enabled=True)
        self._reloadevts = ControlButton('Reload events', enabled=True, default=self.__reload_events_btn_evt)
        ################################################################

        #### rotation ##################################################
        self._userotup          = ControlCheckBox('Turn the contour always up')
        self._userotdown        = ControlCheckBox('Turn the contour always down')
        self._usefixedangle     = ControlCheckBox('Use a fixed orientation')
        self._fixedangle        = ControlSlider('Rotate the images using a fixed angle', enabled=True, default=0, minimum=0, maximum=360)
        self._usedatasetangle   = ControlCheckBox('Use the orientation of other contour')
        self._datasetanglepanel = ControlEmptyWidget('Datasets for the orientation', enabled=True)
        ################################################################

        #### image position ############################################
        self._useposdataset   = ControlCheckBox('Use a dataset to center the image')
        self._datasetpospanel = ControlEmptyWidget('Datasets for the image position', enabled=True)
        ################################################################

        
        self.formset = [
            '_toolbox',
            '_exportdir',
            '_apply',
            '_progress'
        ]

        self.load_order = [
            '_contourspanel','_userotup', '_userotdown',
            '_exportdir','_usemaskimg','_usemaskdilate','_usemaskellipse','_usemaskellipse',
            '_usemaskcircular', '_maskcircularsize', '_usemaskrect', '_margin', '_imagesize',
            '_usestretch', '_eventslst', '_usefixedangle', '_fixedangle', '_usedatasetangle',
            '_datasetanglepanel', '_useposdataset', '_datasetpospanel', '_usecut', '_cuty', '_cutx'
        ]

        #datasets painel
        self.datasets_dialog = DatasetsDialog(self)
        self.datasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self._contourspanel.value = self.datasets_dialog

        self.posdatasets_dialog = DatasetsDialog(self)
        self.posdatasets_dialog.datasets_filter = lambda x: isinstance(x, (Contours,Path) )
        self._datasetpospanel.value = self.posdatasets_dialog

        self.orientdatasets_dialog = DatasetsDialog(self)
        self.orientdatasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self.orientdatasets_dialog.interval_visible = False
        self._datasetanglepanel.value = self.orientdatasets_dialog


        self._apply.value       = self.__apply_event
        self._apply.icon        = conf.ANNOTATOR_ICON_PATH

        self._imagesize.changed_event = self.__image_size_changed_evt

        self._toolbox.value = [
            ('Extract from contours',(
                self.datasets_dialog,
            )),
            ('Mask',(
                self._usemaskimg,
                (self._usemaskdilate,self._maskdilatesize),
                (self._usemaskcircular,self._maskcircularsize),
                (self._usemaskellipse,self._usemaskrect),
            )),
            ('Margin, image size and stretch image',(
                self._usestretch,
                self._margin, 
                self._imagesize,
                self._usecut,
                self._cutx,
                self._cuty
            )),
            ('Rotate images',(
                (self._userotup, self._userotdown),
                (self._usefixedangle, self._fixedangle),
                self._usedatasetangle,
                self._datasetanglepanel
            )),
            ('Center images',(
                self._useposdataset,
                self._datasetpospanel,
            )),
            ('Export images per events',(
                self._reloadevts,
                self._eventslst,
            )),
        ]

        self.__reload_events_btn_evt()
        self.__image_size_changed_evt()

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    def __image_size_changed_evt(self):
        if self._imagesize.value>0:
            self._usecut.enabled = True
            self._cutx.enabled = True
            self._cuty.enabled = True
            self._cuty.max = self._imagesize.value
            self._cutx.max = self._imagesize.value
        else:
            self._usecut.enabled = False
            self._cutx.enabled = False
            self._cuty.enabled = False

    def __reload_events_btn_evt(self):
        """
        Find all the events available on the timeline
        """
        timeline = self.mainwindow.timeline
        rows     = timeline.rows

        events   = {}
        for row in rows:
            for event in row.events:
                events[event.title] = True

        events = sorted(events.keys())

        loaded_events = dict(self._eventslst.items)
        self._eventslst.value = [(e, loaded_events.get(e, False)) for e in events]


  
    ###########################################################################
    ### PROPERTIES ############################################################
    ###########################################################################

    @property
    def datasets(self): return self.datasets_dialog.datasets
    

    @property
    def player(self): return self._filter._player


    def __get_events_cuts(self, begin, end):
        ### calculate the video cuts #############################
        selected_events = self._eventslst.value
        videocuts       = []
        if len(selected_events):
            # use the events to cut the video
            totalframes = 0
            timeline    = self.mainwindow.timeline

            for row in timeline.rows:
                for event in row.events:
                    if event.end<=begin: continue
                    if event.begin>=end: continue
                    if event.title not in selected_events: continue
                    b = int(event.begin if event.begin>=begin else begin)
                    e = int(event.end   if event.end<=end else end)
                    totalframes += e-b
                    videocuts.append( (b, e, event.title) )
            videocuts = sorted(videocuts, key = lambda x: x[0])
        else:
            # no events were selected
            totalframes = end-begin
            videocuts   = [(int(begin), int(end), None)]
        ##########################################################
        return videocuts

    def __get_export_map(self, begin_frame, end_frame, eventscuts):
        """
        Create a map of folders to export the images to
        """
        exportmap = []

        for begin, end, title in eventscuts:
            if title is None: continue

            for i in range(begin, end):

                # fill the map with empty values
                if len(exportmap)<=i:
                    while len(exportmap)<=i:
                        exportmap.append(None)

                if exportmap[i] is None: exportmap[i]=[]

                exportmap[i].append(title)


        for i in range(begin_frame, end_frame):
            # fill the map with empty values
            if len(exportmap)<=i:
                while len(exportmap)<=i:
                    exportmap.append(None)

            if exportmap[i] is None: exportmap[i]=[]

            if len(exportmap[i])==0:
                exportmap[i].append('untagged')
            
        return exportmap



    def __apply_event(self):

        if self._apply.checked:

            if self._usecut.value and self._imagesize.value>0:
                x, xx = self._cutx.value
                y, yy = self._cuty.value
                if int(yy)==int(y) or int(xx)==int(x):
                    self.message("The second cut value has to be bigger than the first", "Error", "error")
                    self._apply.checked=False
                    return

            self._toolbox.enabled   = False
            self._exportdir.enabled = False
            self._progress.value    = 0
            self._apply.label       = 'Cancel'

            # setup the progress bar
            total_2_analyse  = 0
            for video, (begin, end), datasets in self.datasets_dialog.selected_data:
                total_2_analyse += end-begin

            self._progress.min = 0
            self._progress.max = total_2_analyse
            self._progress.show()


            ######################################################################
            # create a directory to export the images if the option was selected
            EXPORT_DIRECTORY = self._exportdir.value
            if len(EXPORT_DIRECTORY)==0: EXPORT_DIRECTORY = 'contour-images'
            if not os.path.exists(EXPORT_DIRECTORY): os.makedirs(EXPORT_DIRECTORY)
            ######################################################################

         
            ############ CONFIGURE IMAGE CUT PARAMETERS ##########################
            params = {}
            params['mask']          = self._usemaskimg.value
            params['ellipse_mask']  = self._usemaskellipse.value
            params['rect_mask']     = self._usemaskrect.value
            params['margin']        = self._margin.value
            params['stretch']       = self._usestretch.value

            if self._usemaskdilate.value:
                params['mask']  = int(self._maskdilatesize.value)
            if self._usemaskcircular.value:
                params['circular_mask'] = int(self._maskcircularsize.value)
            if self._usefixedangle.value:
                params['angle'] = math.radians(self._fixedangle.value)
            if self._userotup.value:
                params['angle'] = 'up'
            if self._userotdown.value:
                params['angle'] = 'down'
            if self._imagesize.value>0:
                params['size']  = (self._imagesize.value, self._imagesize.value)
            ######################################################################

            ######################################################################            
            # check if should use the angle from other datasets
            if self._usedatasetangle.value:
                objects_angles = {}
                for _, _, datasets in self.datasets_dialog.selected_data:
                    for dataset in datasets:
                        for _, _, d in self._datasetanglepanel.value.selected_data:
                            objects_angles[dataset.object2d] = d[0]
            ######################################################################

            ######################################################################            
            # check if should use position from other datasets
            if self._useposdataset.value:
                objects_pos = {}
                for _, _, datasets in self.datasets_dialog.selected_data:
                    for dataset in datasets:
                        for _, _, d in self._datasetpospanel.value.selected_data:
                            objects_pos[dataset.object2d] = d[0]
            ######################################################################

                


            for video, (begin, end), datasets in self.datasets_dialog.selected_data:
                if not self._apply.checked: break

                if len(datasets)==0: continue
                begin, end  = int(begin), int(end)
                capture     = cv2.VideoCapture(video.filepath)
                capture.set(cv2.CAP_PROP_POS_FRAMES, begin); 
                
                eventscuts = self.__get_events_cuts(begin, end)
                exportmap  = self.__get_export_map(begin, end, eventscuts) 

                ######################################################################
                # create the directories to export the images per video and events
                videofolder = os.path.join(EXPORT_DIRECTORY, video.name)
                if not os.path.exists(videofolder): os.makedirs(videofolder)

                for dataset in datasets:
                    objectfolder = os.path.join(videofolder, dataset.object2d.name)
                    if not os.path.exists(objectfolder): os.makedirs(objectfolder)

                    datasetfolder = os.path.join(objectfolder, dataset.name)
                    if not os.path.exists(datasetfolder): os.makedirs(datasetfolder)
                ######################################################################

                for i in range(begin,end):
                    if not self._apply.checked: break

                    res, frame = capture.read()
                    #exit in the case the frame was not read.
                    if not res:
                        self._apply.label       = 'Apply'
                        self._toolbox.enabled   = True
                        self._exportdir.enabled = True
                        self._apply.checked     = False
                        self._progress.hide()       
                        return False, None

                    for foldername in exportmap[i]:
                        if not self._apply.checked: break
                       
                        for dataset in datasets:

                            parameters = dict(params)
                            parameters['frame'] = frame.copy()

                            # in the case we are using another dataset angle to rotate the image
                            if self._usedatasetangle.value:
                                dtangle = objects_angles.get(dataset.object2d, None)
                                if dtangle is not None:
                                    parameters['angle'] = dtangle.get_angle(i)
                                else:
                                    continue

                            if self._useposdataset.value:
                                dpos = objects_pos.get(dataset.object2d, None)
                                if dpos is not None:
                                    parameters['image_center'] = dpos.get_position(i)
                                else:
                                    continue

                            ok, img = dataset.get_image(i, **parameters)
                            if ok:
                                folder  = os.path.join(videofolder, dataset.object2d.name, dataset.name, foldername)
                                imgpath = os.path.join(folder, '{0}.png'.format(i) )
                                if not os.path.exists(folder): os.makedirs(folder)

                                if self._usecut.value and self._imagesize.value>0:
                                    x, xx = self._cutx.value
                                    y, yy = self._cuty.value
                                    img = img[int(y):int(yy), int(x):int(xx)]

                                cv2.imwrite(imgpath, img)

                    self._progress.value += 1
                
                

            self._apply.label       = 'Apply'
            self._toolbox.enabled   = True
            self._exportdir.enabled = True
            self._apply.checked     = False
            self._progress.hide()
    def __init__(self, parent=None):
        super(ContoursImagesWindow, self).__init__('Contour images', parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)
        

        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._contourspanel = ControlEmptyWidget('Contours datasets')
        self._progress      = ControlProgress('Progress', visible=False)       
        self._apply         = ControlButton('Apply', checkable=True)
        self._toolbox       = ControlToolBox('Toolbox')
        self._exportdir     = ControlDir('Export images to folder', default='images-from-contour')
        

        #### mask ######################################################
        self._usemaskimg       = ControlCheckBox('Apply a mask to the image')
        self._usemaskdilate    = ControlCheckBox('Dilate the mask and apply it to the image')
        self._maskdilatesize   = ControlSlider('Dilate size', default=0, minimum=0, maximum=100)
        self._usemaskellipse   = ControlCheckBox('Apply the min. ellipse as a mask to the image')
        self._usemaskcircular  = ControlCheckBox('Apply a circular mask to the image')
        self._maskcircularsize = ControlSlider('Circular radius', default=0, minimum=0, maximum=100)
        self._usemaskrect      = ControlCheckBox('Apply the min. rect as a mask to the image')
        ################################################################

        #### margin ####################################################
        self._margin = ControlSlider('Margin size', default=0, minimum=0, maximum=100)
        ################################################################

        #### imagesize #################################################
        self._imagesize = ControlSlider('Image size', default=0, minimum=0, maximum=400)
        ################################################################

        #### cut #######################################################
        self._usecut = ControlCheckBox('Cut image')
        self._cutx = ControlBoundingSlider('X cut', default=(10,30), minimum=0, maximum=1000)
        self._cuty = ControlBoundingSlider('Y cut', default=(10,30), minimum=0, maximum=1000)
        ################################################################
        

        #### use stretch ###############################################
        self._usestretch = ControlCheckBox('Stretch image')
        ################################################################

        #### filter per events #########################################
        self._eventslst  = ControlCheckBoxList('Events', enabled=True)
        self._reloadevts = ControlButton('Reload events', enabled=True, default=self.__reload_events_btn_evt)
        ################################################################

        #### rotation ##################################################
        self._userotup          = ControlCheckBox('Turn the contour always up')
        self._userotdown        = ControlCheckBox('Turn the contour always down')
        self._usefixedangle     = ControlCheckBox('Use a fixed orientation')
        self._fixedangle        = ControlSlider('Rotate the images using a fixed angle', enabled=True, default=0, minimum=0, maximum=360)
        self._usedatasetangle   = ControlCheckBox('Use the orientation of other contour')
        self._datasetanglepanel = ControlEmptyWidget('Datasets for the orientation', enabled=True)
        ################################################################

        #### image position ############################################
        self._useposdataset   = ControlCheckBox('Use a dataset to center the image')
        self._datasetpospanel = ControlEmptyWidget('Datasets for the image position', enabled=True)
        ################################################################

        
        self.formset = [
            '_toolbox',
            '_exportdir',
            '_apply',
            '_progress'
        ]

        self.load_order = [
            '_contourspanel','_userotup', '_userotdown',
            '_exportdir','_usemaskimg','_usemaskdilate','_usemaskellipse','_usemaskellipse',
            '_usemaskcircular', '_maskcircularsize', '_usemaskrect', '_margin', '_imagesize',
            '_usestretch', '_eventslst', '_usefixedangle', '_fixedangle', '_usedatasetangle',
            '_datasetanglepanel', '_useposdataset', '_datasetpospanel', '_usecut', '_cuty', '_cutx'
        ]

        #datasets painel
        self.datasets_dialog = DatasetsDialog(self)
        self.datasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self._contourspanel.value = self.datasets_dialog

        self.posdatasets_dialog = DatasetsDialog(self)
        self.posdatasets_dialog.datasets_filter = lambda x: isinstance(x, (Contours,Path) )
        self._datasetpospanel.value = self.posdatasets_dialog

        self.orientdatasets_dialog = DatasetsDialog(self)
        self.orientdatasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self.orientdatasets_dialog.interval_visible = False
        self._datasetanglepanel.value = self.orientdatasets_dialog


        self._apply.value       = self.__apply_event
        self._apply.icon        = conf.ANNOTATOR_ICON_PATH

        self._imagesize.changed_event = self.__image_size_changed_evt

        self._toolbox.value = [
            ('Extract from contours',(
                self.datasets_dialog,
            )),
            ('Mask',(
                self._usemaskimg,
                (self._usemaskdilate,self._maskdilatesize),
                (self._usemaskcircular,self._maskcircularsize),
                (self._usemaskellipse,self._usemaskrect),
            )),
            ('Margin, image size and stretch image',(
                self._usestretch,
                self._margin, 
                self._imagesize,
                self._usecut,
                self._cutx,
                self._cuty
            )),
            ('Rotate images',(
                (self._userotup, self._userotdown),
                (self._usefixedangle, self._fixedangle),
                self._usedatasetangle,
                self._datasetanglepanel
            )),
            ('Center images',(
                self._useposdataset,
                self._datasetpospanel,
            )),
            ('Export images per events',(
                self._reloadevts,
                self._eventslst,
            )),
        ]

        self.__reload_events_btn_evt()
        self.__image_size_changed_evt()
예제 #25
0
    def __init__(self, parent=None):
        super(VideosExporterGui, self).__init__('Videos exporter',
                                                parent_win=parent)

        self.set_margin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(400)

        self._toolbox = ControlToolBox('Tool')

        self._panel_area = ControlEmptyWidget('Set the object area',
                                              default=DatasetsDialog(self))
        self._panel_colors = ControlEmptyWidget('Set the object color',
                                                default=DatasetsDialog(self))
        self._panel_imgs = ControlEmptyWidget('Set the video background',
                                              default=ImagesDialog(self))

        #### path panel ################################################
        self._panel_path = ControlEmptyWidget('Set the object path',
                                              default=DatasetsDialog(self))
        self._drawpath = ControlCheckBox('Draw paths')
        ################################################################

        #### draw events ###############################################
        self._drawevents = ControlCheckBoxList('Events')
        self._eventstitles = ControlCheckBox('Draw titles')
        self._evtsreload1 = ControlButton('Reload events')
        ################################################################

        #### split by events ###########################################
        self._splitevents = ControlCheckBoxList('Events')
        self._evtsreload2 = ControlButton('Reload events')
        ################################################################

        self._codec = ControlCheckBox('Force AVI')
        self._outdir = ControlDir('Output directory')
        self._outfile = ControlText('Output file name')

        self._player = ControlPlayer('Player')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Export video(s)', checkable=True)
        self._apply.icon = conf.ANNOTATOR_ICON_PATH
        self._apply.enabled = False

        self._usefixedsize = ControlCheckBox('Use a fixed size')
        self._usefixedcolor = ControlCheckBox('Use a fixed color')
        self._radius = ControlSlider('Circle radius',
                                     default=10,
                                     minimum=1,
                                     maximum=300)
        self._color = ControlText('BGR color', default='255,255,255')

        self.formset = [('_toolbox', '||', '_player'), '=', '_outdir',
                        ('_outfile', '_codec'), '_apply', '_progress']

        self._toolbox.value = [
            ('Path', [self._panel_path, self._drawpath]),
            ('Circle (optional)',
             [self._panel_area, (self._usefixedsize, self._radius)]),
            ('Circle color (optional)',
             [self._panel_colors, (self._usefixedcolor, self._color)]),
            ('Background (optional)', [self._panel_imgs]),
            ('Draw events (optional)',
             [self._evtsreload1, self._drawevents, self._eventstitles]),
            ('Split files by events (optional)',
             [self._evtsreload2, self._splitevents]),
        ]

        self._panel_path.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path))
        #self._panel_area.value.datasets_filter   = lambda x: isinstance(x, Value )
        self._panel_colors.value.datasets_filter = lambda x: isinstance(
            x, (Contours, Path)) and hasattr(x, 'has_colors_avg'
                                             ) and x.has_colors_avg

        ### Set the controls events #############################################
        self._evtsreload1.value = self.__reload_events
        self._evtsreload2.value = self.__reload_events
        self._outfile.changed_event = self.outputfile_changed_event
        self._usefixedsize.changed_event = self.__usefixedsize_changed_event
        self._usefixedcolor.changed_event = self.__usefixedcolor_changed_event
        self._splitevents.selection_changed_event = self.outputfile_changed_event
        self._panel_path.value.video_selection_changed_event = self.__video_selection_changed_event
        self._codec.changed_event = self.__video_selection_changed_event
        ## function from VideosExporterProcess class
        self._apply.value = self.apply_event
        ## function from VideosExporterPreview class
        self._player.process_frame_event = self.player_processframe_event

        self._evtsreload1.icon = conf.ANNOTATOR_ICON_REFRESH
        self._evtsreload2.icon = conf.ANNOTATOR_ICON_REFRESH

        self._progress.hide()
        self._radius.hide()
        self._color.hide()
        self.__check_areatab_event()
예제 #26
0
class SmoothPathsWindow(BaseWidget):
    def __init__(self, parent=None):
        super(SmoothPathsWindow, self).__init__('Smooth paths',
                                                parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)
        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._datasets_panel = ControlEmptyWidget('Paths')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)

        self._winsize = ControlSlider('Window size',
                                      minimum=3,
                                      default=3,
                                      maximum=100)
        self._order = ControlSlider('Order', minimum=0, default=0, maximum=10)
        self._deriv = ControlSlider('Derivative',
                                    minimum=0,
                                    default=0,
                                    maximum=10)
        self._rate = ControlSlider('Rate', minimum=0, default=0, maximum=10)

        self._formset = [
            '_datasets_panel', '=', '_winsize', '_order', '_deriv', '_rate',
            ' ', '_apply', '_progress'
        ]

        self.load_order = ['_datasets_panel']

        self.datasets_dialog = DatasetsDialog(self)
        self._datasets_panel.value = self.datasets_dialog
        self.datasets_dialog.datasets_filter = lambda x: isinstance(
            x, (Path, Value))

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()

    def init_form(self):
        super(SmoothPathsWindow, self).init_form()
        self.datasets_dialog.project = self.mainwindow.project

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    ###########################################################################
    ### PROPERTIES ############################################################
    ###########################################################################

    @property
    def datasets(self):
        return self.datasets_dialog.datasets

    def __apply_event(self):

        if self._apply.checked:

            if self._winsize.value < self._order.value + 2:
                self.message(
                    'The Window size has to be bigger than the Order + 2 ',
                    'Error', 'error')
                self._apply.checked = False
                return

            if self._order.value < self._deriv.value:
                self.message(
                    'The Derivative has to be less than or equal to the Order',
                    'Error', 'error')
                self._apply.checked = False
                return

            if len(self.datasets_dialog.datasets) == 0:
                self.message('You have to select at least one dataset',
                             'Error', 'error')
                self._apply.checked = False
                return

            self._datasets_panel.enabled = False
            self._apply.label = 'Cancel'

            total_2_analyse = 0
            for video, (begin,
                        end), datasets in self.datasets_dialog.selected_data:
                total_2_analyse += (end - begin + 1) * 2

            self._progress.min = 0
            self._progress.max = total_2_analyse
            self._progress.show()

            count = 0
            for video, (begin,
                        end), datasets in self.datasets_dialog.selected_data:
                begin = int(begin)
                end = int(end) + 1

                for dataset in datasets:
                    if isinstance(dataset, Path):
                        values = [
                            dataset.get_position(index)
                            for index in range(begin, end)
                        ]
                    elif isinstance(dataset, Value):
                        values = [
                            dataset.get_value(index)
                            for index in range(begin, end)
                        ]

                    #remove the None positions
                    for curr_idx in range(len(values)):
                        if values[curr_idx] is None:

                            #Search for a not None position on the past
                            new_vals = None
                            for prev_idx in range(curr_idx, 0, -1):
                                new_vals = values[prev_idx]
                                if new_vals is not None: break

                            #Search for a not None position on the future
                            if new_vals is None:
                                for nex_idx in range(curr_idx, end):
                                    new_vals = values[nex_idx]
                                    if new_vals is not None: break

                            #No positions were found, assume 0,0 position
                            if new_vals is None:
                                if isinstance(dataset, Path):
                                    new_vals = (0, 0)
                                elif isinstance(dataset, Value):
                                    new_vals = 0

                            values[curr_idx] = new_vals

                        self._progress.value = count
                        count += 1

                    winsize = self._winsize.value
                    winsize = winsize + 1 if (winsize % 2) == 0 else winsize

                    if isinstance(dataset, Path):
                        xs = np.array([x for x, y in values])
                        ys = np.array([y for x, y in values])
                        xs = savitzky_golay(xs, winsize, self._order.value,
                                            self._deriv.value,
                                            self._rate.value)
                        ys = savitzky_golay(ys, winsize, self._order.value,
                                            self._deriv.value,
                                            self._rate.value)
                        for index in range(begin, end):
                            pos = dataset.get_position(index)
                            if pos is not None:
                                dataset.set_position(index, xs[index],
                                                     ys[index])
                            self._progress.value = count
                            count += 1
                    elif isinstance(dataset, Value):
                        xs = np.array(values)
                        xs = savitzky_golay(xs, winsize, self._order.value,
                                            self._deriv.value,
                                            self._rate.value)
                        for index in range(begin, end):
                            val = dataset.get_value(index)
                            if val is not None:
                                dataset.set_value(index, xs[index])
                            self._progress.value = count
                            count += 1

            self._datasets_panel.enabled = True
            self._apply.label = 'Apply'
            self._apply.checked = False
            self._progress.hide()
class ExportWindow(BaseWidget):
    def __init__(self, parent=None):
        BaseWidget.__init__(self, 'Export data', parent_win=parent)

        self.set_margin(5)
        self.setMinimumHeight(600)
        self.setMinimumWidth(800)

        self._tree = ControlTree('Data')
        self._apply = ControlButton('Apply', checkable=True)
        self._progress = ControlProgress('Progress')
        self._add = ControlButton('Add')
        self._remove = ControlButton('Remove')
        self._export_list = ControlList('Columns to export')

        self._outdir = ControlDir('Output directory')
        self._outfile = ControlText('Output file name')

        self._toggleevts = ControlCheckBox('Split files by events')
        self._splitevents = ControlCheckBoxList('Events')
        self._evtsreload = ControlButton('Reload events')

        self._formset = [[['_add', '_tree'], '||',
                          ['_remove', '_export_list']], '_toggleevts',
                         '_evtsreload', '_splitevents', '_outdir', '_outfile',
                         '_apply', '_progress']

        self._add.value = self.__add_column_event
        self._remove.value = self.__remove_column_event
        self._apply.value = self.__apply_btn_event
        self._evtsreload.value = self.__reload_events
        self._outdir.changed_event = self.__update_outfile_name_event
        self._outfile.changed_event = self.__update_outfile_name_event
        self._toggleevts.changed_event = self.__toggleevents_visibility
        self._splitevents.changed_event = self.__update_outfile_name_event
        self._splitevents.selection_changed_event = self.__update_outfile_name_event

        self._tree.show_header = False
        self._apply.icon = conf.ANNOTATOR_ICON_MOTION
        self._evtsreload.icon = conf.ANNOTATOR_ICON_REFRESH
        self._add.icon = conf.ANNOTATOR_ICON_ADD
        self._remove.icon = conf.ANNOTATOR_ICON_REMOVE

        self._progress.hide()
        self._splitevents.hide()
        self._evtsreload.hide()
        self._apply.enabled = False

        self._properties = []

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    def __toggleevents_visibility(self):
        if self._toggleevts.value:
            self._splitevents.show()
            self._evtsreload.show()
        else:
            self._splitevents.hide()
            self._evtsreload.hide()

    def __field_full_name(self, tree_item):
        name = tree_item.text(0)
        while True:
            tree_item = tree_item.parent()
            if tree_item is None: break
            name = "{0} > {1}".format(tree_item.text(0), name)
        return name

    def __add_column_event(self):
        self.__update_outfile_name_event()
        item = self._tree.selected_item

        if item is None:
            return

        if hasattr(item, 'data_function'):
            self._export_list += [self.__field_full_name(item)]
            self._properties.append((len(item.win), item.data_function))
        elif isinstance(item.win, Value):
            self._export_list += [self.__field_full_name(item)]
            self._properties.append((len(item.win), item.win.get_value))

    def __remove_column_event(self):
        self.__update_outfile_name_event()
        if self._export_list.selected_row_index is None:
            return
        elif self._export_list.selected_row_index >= 0:
            self._properties.pop(self._export_list.selected_row_index)
            self._export_list -= -1

    def __update_outfile_name_event(self):
        """
		Update the output filename
		"""
        filename = self._outfile.value
        if len(filename.strip()) == 0: return

        outfilepath, outfile_extension = os.path.splitext(filename)
        names = [outfilepath] if len(outfilepath) > 0 else []

        if len(list(self._splitevents.value)) > 0:
            if '{event}' not in outfilepath: names.append('{event}')
            if '{start}' not in outfilepath: names.append('{start}')
            if '{end}' not in outfilepath: names.append('{end}')

        self._outfile.value = ('-'.join(names) + '.csv')
        self._apply.enabled = True

    def __apply_btn_event(self):

        if self._apply.checked:

            if len(self._properties) == 0:
                QMessageBox.about(
                    self, "Error",
                    "You need to select at least one value to export.")
                self._apply.checked = False
                return

            if self._outfile.value is None or len(
                    self._outfile.value.strip()) == 0:
                QMessageBox.about(
                    self, "Error",
                    "You need to select the name of the output file.")
                self._apply.checked = False
                return

            if self._outdir.value is None or len(self._outdir.value) == 0:
                QMessageBox.about(
                    self, "Error",
                    "You need to select the name of the output directory.")
                self._apply.checked = False
                return

            self.__update_outfile_name_event()

            self._export_list.enabled = False
            self._tree.enabled = False
            self._add.enabled = False
            self._remove.enabled = False
            self._outdir.enabled = False
            self._outfile.enabled = False
            self._apply.label = 'Cancel'

            ### calculate the video cuts #############################
            timeline = self.parent().timeline

            selected_events = self._splitevents.value
            videocuts = []
            if len(selected_events):
                # use the events to cut the video
                totalframes = 0
                for row in timeline.rows:
                    for event in row.events:
                        if event.title not in selected_events: continue
                        b = event.begin
                        e = event.end
                        totalframes += e - b
                        videocuts.append((int(b), int(e), event.title))
                videocuts = sorted(videocuts, key=lambda x: x[0])
            else:
                # no events were selected
                end = max([size for size, func in self._properties])
                totalframes = end
                videocuts = [(0, int(end), None)]
            ##########################################################

            self._progress.min = 0
            self._progress.max = totalframes
            self._progress.show()

            for b, e, eventname in videocuts:

                filename = self._outfile.value
                filename = filename.format(event=eventname, start=b, end=e)
                filename = os.path.join(self._outdir.value, filename)

                with open(filename, 'w') as out:

                    ## write the csv columns headers
                    out.write('frame;')
                    for values in self._export_list.value:
                        out.write(('{0};'.format(values[0])))
                    out.write('\n')

                    ## write the values
                    for index in range(b, e):
                        out.write('{0};'.format(index))
                        for _, func in self._properties:
                            out.write('{0};'.format(func(index)))
                        out.write('\n')
                        self._progress += 1

            self._export_list.enabled = True
            self._tree.enabled = True
            self._add.enabled = True
            self._remove.enabled = True
            self._outdir.enabled = True
            self._outfile.enabled = True
            self._apply.label = 'Apply'
            self._apply.checked = False
            self._progress.hide()

    def __copy_tree_node(self, item, new_item):
        new_item.win = item.win
        if hasattr(item, 'data_function'):
            new_item.data_function = item.data_function

    def __reload_events(self):
        """
		Find all the events available on the timeline
		"""
        timeline = self.parent().timeline
        rows = timeline.rows

        events = {}
        for row in rows:
            for event in row.events:
                events[event.title] = True

        events = sorted(events.keys())

        loaded_events = dict(self._splitevents.items)
        self._splitevents.value = [(e, loaded_events.get(e, False))
                                   for e in events]

    @property
    def project(self):
        return self._project

    @project.setter
    def project(self, value):
        self._project = value
        self._tree.clear()
        self._tree.clone_tree(value.tree, copy_function=self.__copy_tree_node)
        self.__reload_events()
예제 #28
0
    def __init__(self):
        super(MultipleBlobDetection, self).__init__('Multiple Blob Detection')

        # Definition of the forms fields
        self._videofile = ControlFile('Video')
        self._outputfile = ControlText('Results output file')

        self._threshold_box = ControlCheckBox('Threshold')
        self._threshold = ControlSlider('Binary Threshold')
        self._threshold.value = 114
        self._threshold.min = 1
        self._threshold.max = 255
        self._roi_x_min = ControlSlider('ROI x top')
        self._roi_x_max = ControlSlider('ROI x bottom')
        self._roi_y_min = ControlSlider('ROI y left')
        self._roi_y_max = ControlSlider('ROI y right')
        # self._blobsize = ControlSlider('Minimum blob size', 100, 100, 2000)
        self._player = ControlPlayer('Player')
        self._runbutton = ControlButton('Run')
        self._start_frame = ControlText('Start Frame')
        self._stop_frame = ControlText('Stop Frame')

        self._color_list = ControlCombo('Color channels')
        self._color_list.add_item('Red Image Channel', 2)
        self._color_list.add_item('Green Image Channel', 1)
        self._color_list.add_item('Blue Image Channel', 0)

        self._clahe = ControlCheckBox('CLAHE      ')
        self._dilate = ControlCheckBox('Morphological Dilation')
        self._dilate_type = ControlCombo('Dilation Kernel Type')
        self._dilate_type.add_item('RECTANGLE', cv2.MORPH_RECT)
        self._dilate_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE)
        self._dilate_type.add_item('CROSS', cv2.MORPH_CROSS)
        self._dilate_size = ControlSlider('Dilation Kernel Size',
                                          default=3,
                                          min=1,
                                          max=10)
        self._dilate_size.value = 5
        self._dilate_size.min = 1
        self._dilate_size.max = 10

        self._erode = ControlCheckBox('Morphological Erosion')
        self._erode_type = ControlCombo('Erode Kernel Type')
        self._erode_type.add_item('RECTANGLE', cv2.MORPH_RECT)
        self._erode_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE)
        self._erode_type.add_item('CROSS', cv2.MORPH_CROSS)

        self._erode_size = ControlSlider('Erode Kernel Size')
        self._erode_size.value = 5
        self._erode_size.min = 1
        self._erode_size.max = 10

        self._open = ControlCheckBox('Morphological Opening')
        self._open_type = ControlCombo('Open Kernel Type')
        self._open_type.add_item('RECTANGLE', cv2.MORPH_RECT)
        self._open_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE)
        self._open_type.add_item('CROSS', cv2.MORPH_CROSS)

        self._open_size = ControlSlider('Open Kernel Size')
        self._open_size.value = 20
        self._open_size.min = 1
        self._open_size.max = 40

        self._close = ControlCheckBox('Morphological Closing')
        self._close_type = ControlCombo('Close Kernel Type')
        self._close_type.add_item('RECTANGLE', cv2.MORPH_RECT)
        self._close_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE)
        self._close_type.add_item('CROSS', cv2.MORPH_CROSS)
        self._close_size = ControlSlider('Close Kernel Size',
                                         default=19,
                                         min=1,
                                         max=40)
        self._close_size.value = 20
        self._close_size.min = 1
        self._close_size.max = 40

        self._LoG = ControlCheckBox('LoG - Laplacian of Gaussian')
        self._LoG_size = ControlSlider('LoG Kernel Size')
        self._LoG_size.value = 20
        self._LoG_size.min = 1
        self._LoG_size.max = 60

        self._progress_bar = ControlProgress('Progress Bar')

        # Define the function that will be called when a file is selected
        self._videofile.changed_event = self.__video_file_selection_event
        # Define the event that will be called when the run button is processed
        self._runbutton.value = self.__run_event
        # Define the event called before showing the image in the player
        self._player.process_frame_event = self.__process_frame

        self._error_massages = {}

        # Define the organization of the Form Controls
        self.formset = [
            ('_videofile', '_outputfile'), ('_start_frame', '_stop_frame'),
            ('_color_list', '_clahe', '_roi_x_min', '_roi_y_min'),
            ('_threshold_box', '_threshold', '_roi_x_max', '_roi_y_max'),
            ('_dilate', '_erode', '_open', '_close'),
            ('_dilate_type', '_erode_type', '_open_type', '_close_type'),
            ('_dilate_size', '_erode_size', '_open_size', '_close_size'),
            ('_LoG', '_LoG_size'), ('_runbutton', '_progress_bar'), '_player'
        ]
        self.is_roi_set = False
예제 #29
0
    def __init__(self, *args, **kwargs):
        super().__init__('Hazard Labelling')

        self._args = {  "filepath": FILEPATH,
                        "folder": FOLDER,
                        "dest": DEST
                        }

        self.set_margin(10)

        #Definition of the forms fields
        self._videofile = ControlFile('Video')
        self._hazardbutton = ControlButton('Hazard')
        self._next = ControlButton('Next Video')
        self._save_data = ControlButton('Save labels')
        self._player = ControlPlayer('Player')
        self._timeline = ControlEventTimeline('Timeline')
        self._panel = ControlDockWidget(label='Timeline', side='bottom', margin=10)
        self._status = ControlText('Status')
        self._file_list = []

        if self._args["folder"] is None:
            if self._args["filepath"] is not None:
                self._file_list = self._args["filepath"]
        elif self._args["folder"] is not None:
            if os.path.isdir(self._args["folder"]):
                self.__updateStatus("Source folder found at: {}".format(self._args["folder"]))
                print("Scanning folder and all subfolders... {}".format(self._args["folder"]))
                count = 0
                for (dirpath, dirnames, filenames) in os.walk(self._args["folder"]):
                    path = []
                    for f in filenames:
                        if f.rsplit('.')[-1] in ACCEPTABLE_EXT:
                            count += 1
                            path.append(dirpath + "/" + f)
                    self._file_list.extend(path)
                    if count % 100 == 0:
                        print("Found {} files...".format(count))
                print("Scan complete, found {} acceptable files".format(count))
        self._video_count = len(self._file_list)
        self._progress = ControlProgress(label="Video %p of " + str(self._video_count), defaultValue=1, min=1, max=self._video_count)

        self._hazard_counter = 0
        self._current_video = 0

        #Define function calls on button presses
        self._videofile.changed_event = self.__videoFileSelectionEvent
        self._hazardbutton.value = self.__labelHazard
        self._next.value = self.__nextVideo
        self._save_data.value = self.__saveData
        self._panel.value = self._timeline
        self._progress.value = self._current_video + 1

        #Define events
        self._player.process_frame_event = self.__processFrame
        self._player.click_event = self.__clickEvent
        self._player.key_release_event = self.__tagEvent

        #Define the organization of the Form Controls
        self._formset = [
            '_player',
            # '_hazardbutton',
            '_panel',
            ('_videofile', '_next'),
            ('_status', '_save_data'),
            '_progress'
            ]

        self._video_loaded = False

        try:
            self.__videoFileSelect(self._file_list[self._current_video])
        except Exception as e:
            self.__updateStatus("Select video...")

        self._hazard_default_duration = 0
예제 #30
0
class FindOrientationWindow(BaseWidget):
    def __init__(self, parent=None):
        super(FindOrientationWindow,
              self).__init__('Estimate countour orientation',
                             parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)

        self.setMinimumHeight(300)
        self.setMinimumWidth(300)

        self._panel = ControlEmptyWidget('Videos')
        self._progress = ControlProgress('Progress')
        self._apply = ControlButton('Apply', checkable=True)
        self._debug = ControlCheckBox('Create all the intermediate values')

        self._min_steps = ControlSlider('Minimum steps',
                                        default=20,
                                        minimum=1,
                                        maximum=1000)
        self._min_dist = ControlSlider('Minimum distance',
                                       default=30,
                                       minimum=1,
                                       maximum=1000)

        self._panel.value = self.contours_dialog = DatasetsDialog(self)
        self.contours_dialog.datasets_filter = lambda x: isinstance(
            x, Contours)

        self._formset = [
            '_panel', ('_min_steps', '_min_dist'), '_debug', '_apply',
            '_progress'
        ]

        self._apply.value = self.__apply_event
        self._apply.icon = conf.ANNOTATOR_ICON_PATH

        self._progress.hide()

    def init_form(self):
        super(FindOrientationWindow, self).init_form()

    ###########################################################################
    ### EVENTS ################################################################
    ###########################################################################

    ###########################################################################
    ### PROPERTIES ############################################################
    ###########################################################################

    def __apply_event(self):
        IMAGE_SIZE = 150

        if self._apply.checked and self._apply.label == 'Apply':
            self._panel.enabled = False
            self._apply.label = 'Cancel'
            self._min_dist.enabled = False
            self._min_steps.enabled = False

            total_2_analyse = 0
            for video, (begin,
                        end), datasets in self.contours_dialog.selected_data:
                capture = video.video_capture
                total_2_analyse += (end - begin)  #*len(datasets)*1

            self._progress.min = 0
            self._progress.max = total_2_analyse
            self._progress.show()

            debug_mode = self._debug.value

            count = 0
            for video, (begin,
                        end), datasets in self.contours_dialog.selected_data:
                if len(datasets) == 0: continue
                begin, end = int(begin), int(end)

                back_frames = []
                front_frames = []
                for dataset in datasets:

                    for i in range(begin, end):
                        self._progress.value = count
                        count += 1

                        ok, img = dataset.get_image(i,
                                                    mask=True,
                                                    angle='up',
                                                    size=(IMAGE_SIZE,
                                                          IMAGE_SIZE))

                        if ok:
                            cv2.normalize(img, img, 0, 255, cv2.NORM_MINMAX)

                            v1 = img[:int(img.shape[0] /
                                          2)].sum() / np.count_nonzero(
                                              img[:int(img.shape[0] / 2)])
                            v2 = img[int(img.shape[0] /
                                         2):].sum() / np.count_nonzero(
                                             img[int(img.shape[0] / 2):])

                            if v1 < v2:
                                dataset.flip(i)
            """
                    window      = 30
                    min_walked  = 50
                    savitzky_golay_window_size = (window+1 if (window % 2 )==0 else window)

                    if debug_mode:
                        # create the values for debug ##########################################
                        v1 = dataset.object2d.create_value()
                        v1.name = 'Est. orient. - step1 - smoothed walked distance (prev {0} frames)'.format(window)
                        v2 = dataset.object2d.create_value()
                        v2.name = 'Est. orient. - step1 - smoothed walked distance with direction (prev {0} frames)'.format(window)    

                        vflipped = dataset.object2d.create_value()
                        vflipped.name = 'Est. orient. - step1 - flipped images'
                        ########################################################################

                    
                    _, walked_distance     = dataset.calc_walked_distance(window)
                    _, dir_walked_distance = dataset.calc_walked_distance_with_direction(window)
                    walked_distance        = savitzky_golay(np.array(walked_distance), window_size=savitzky_golay_window_size)
                    dir_walked_distance    = savitzky_golay(np.array(dir_walked_distance), window_size=savitzky_golay_window_size)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                    for i in range(begin, end):
                        self._progress.value = count; count+=1
                        if i>=len(walked_distance): continue

                        vflipped.set_value(i, 0)

                        ### Debug ##############################################################
                        if debug_mode: 
                            v1.set_value(i, walked_distance[i])
                            v2.set_value(i, dir_walked_distance[i])
                        ########################################################################

                        if walked_distance[i]>min_walked and dir_walked_distance[i]<-min_walked:
                            dataset.flip(i)

                            if debug_mode: vflipped.set_value(i, 1) 


                    if debug_mode:
                        # create the values for debug ##########################################
                        v1 = dataset.object2d.create_value()
                        v1.name = 'Est. orient. - step2 - smoothed walked distance (prev {0} frames)'.format(window)
                        v2 = dataset.object2d.create_value()
                        v2.name = 'Est. orient. - step2 - smoothed walked distance with direction (prev {0} frames)'.format(window)    

                        vtrainning = dataset.object2d.create_value()
                        vtrainning.name = 'Est. orient. - step2 - good images for trainning'
                        ########################################################################

                    _, walked_distance     = dataset.calc_walked_distance(window)
                    _, dir_walked_distance = dataset.calc_walked_distance_with_direction(window)
                    
                    trainning_frames = []

                    IMAGE_SIZE         = 150
                    MAX_TRAINNING_SET  = 400

                    model = cv2.ml.ANN_MLP_create()
                    layer_sizes = np.int32([IMAGE_SIZE**2, IMAGE_SIZE, IMAGE_SIZE, 2])

                    model.setLayerSizes(layer_sizes)
                    model.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
                    model.setBackpropMomentumScale(0.0)
                    model.setBackpropWeightScale(0.001)
                    model.setTermCriteria((cv2.TERM_CRITERIA_COUNT, 20, 0.01))
                    model.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2, 1)

                    train   = []
                    answers = []
                    for i in range(begin, end):
                        self._progress.value = count; count+=1
                        if i>=len(walked_distance): continue

                        trainning_frames.append(False)
                        if debug_mode: vtrainning.set_value(i, 0)

                        ### Debug ##############################################################
                        if debug_mode: 
                            #v1.set_value(i, walked_distance[i])
                            #v2.set_value(i, dir_walked_distance[i])
                            pass
                        ########################################################################
                        triangle_angle = dataset.get_minimumenclosingtriangle_angle(i)
                        if triangle_angle is None: continue

                        dataset_angle  = dataset.get_angle(i)
                        if dataset_angle is None:  continue

                        if  walked_distance[i]>min_walked and dir_walked_distance[i]>min_walked and \
                            min_dist_angles(dataset_angle, triangle_angle)<(np.pi/2):
                            trainning_frames[i] = True

                            if MAX_TRAINNING_SET is None or len(train)<MAX_TRAINNING_SET:

                                ok1, img_up   = dataset.get_image(i, mask=True, angle='up', size=(IMAGE_SIZE,IMAGE_SIZE) )
                                ok2, img_down = dataset.get_image(i, mask=True, angle='down', size=(IMAGE_SIZE,IMAGE_SIZE) )
                                print(ok1)
                                if ok1 and ok2:
                                    cv2.normalize(img_up, img_up, 0, 255, cv2.NORM_MINMAX)
                                    cv2.normalize(img_down, img_down, 0, 255, cv2.NORM_MINMAX)

                                    train.append(img_up[:,:,0].flatten())
                                    train.append(img_down[:,:,0].flatten())
                                    answers.append([1,0])
                                    answers.append([0,1])

                                    v1.set_value(i, 
                                        img_up[:int(img_up.shape[0]/2)].sum() / np.count_nonzero(img_up[:int(img_up.shape[0]/2)])
                                    )
                                    v2.set_value(i, 
                                        img_up[int(img_up.shape[0]/2):].sum() / np.count_nonzero(img_up[int(img_up.shape[0]/2):])
                                    )

                                    cv2.imwrite('/home/manuel/Desktop/test/{0}.png'.format(i), img_up)
                                    if debug_mode: vtrainning.set_value(i, 1)    
                                

                    print("1")    
                    train   = np.float32(train)
                    answers = np.float32(answers)
                    model.train(train, cv2.ml.ROW_SAMPLE, answers)


                    if debug_mode:
                        # create the values for debug ##########################################
                        v1 = dataset.object2d.create_value()
                        v1.name = 'Est. orient. - step3 - prediction front'
                        v2 = dataset.object2d.create_value()
                        v2.name = 'Est. orient. - step3 - prediction back'
                        v3 = dataset.object2d.create_value()
                        v3.name = 'Est. orient. - step3 - binary prediction'

                    print("2") 
                    
                    for i in range(begin, end):
                        self._progress.value = count; count+=1
                        if i>=len(trainning_frames): continue
                        
                        if debug_mode: v1.set_value(i,0)

                        if not trainning_frames[i]:

                            ok, img = dataset.get_image(i, mask=True, angle='up', size=(IMAGE_SIZE,IMAGE_SIZE) )
                            
                            if ok:
                                cv2.normalize(img, img)
                                
                                _ret, resp = model.predict(np.float32([img[:,:,0].flatten()]))
                                if resp.argmax()==1: dataset.flip(i) 

                                if debug_mode: 
                                    v1.set_value(i,resp[0][0])
                                    v2.set_value(i,resp[0][1]) 
                                    v3.set_value(i,resp.argmax()) 
            """

            self._min_dist.enabled = True
            self._min_steps.enabled = True
            self._panel.enabled = True
            self._apply.label = 'Apply'
            self._apply.checked = False
            self._progress.hide()