class BaseModule(BaseWidget):
    """Application form"""
    def __init__(self):
        global conf
        conf += 'pythonvideoannotator.resources'  # Resources can only be loaded after pyqt is running

        super(BaseModule, self).__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.formset = ['_player']

        self._dock.value = self._time
        self._player.process_frame_event = self.process_frame_event
        self._player.click_event = self.on_player_click_event
        self._time.key_release_event = self.__timeline_key_release_event

        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': []})

    ######################################################################################
    #### FUNCTIONS #######################################################################
    ######################################################################################

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

        if conf.CHART_FILE_PATH: self._time.import_chart(*conf.CHART_FILE_PATH)
        if conf.PROJECT_PATH: self.load_project(conf.PROJECT_PATH)

    ######################################################################################
    #### IO FUNCTIONS ####################################################################
    ######################################################################################

    def save(self, data, project_path=None):
        self._project.save(data, project_path)
        return data

    def load(self, data, project_path=None):
        self._project.load(data, project_path)

    def save_project(self, project_path=None):
        try:
            if project_path is None:
                project_path = QFileDialog.getExistingDirectory(
                    self, "Select the project directory")

            if project_path is not None and str(project_path) != '':
                project_path = str(project_path)
                self.save({}, project_path)
        except Exception as e:
            QMessageBox.critical(self, "Error", str(e))

    def load_project(self, project_path=None):
        if project_path is None:
            project_path = QFileDialog.getExistingDirectory(
                self, "Select the project directory")
        if project_path is not None and str(project_path) != '':
            self.load({}, str(project_path))

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

    def on_player_click_event(self, event, x, y):
        """
		Code to select a blob with the mouse
		"""
        super(VideoAnnotationEditor, self).on_player_click_event(event, x, y)
        self._player.refresh()

    def process_frame_event(self, frame):
        """
		Function called before render each frame
		"""
        return frame

    def __open_project_event(self):
        self.load_project()

    def __save_project_event(self):
        self.save_project(self._project.directory)

    def __save_project_as_event(self):
        self.save_project()

    def __timeline_key_release_event(self, event):
        """
		Control video playback using the space bar to Play/Pause
		"""
        if event.key() == QtCore.Qt.Key_Space:
            self._player.stop(
            ) if self._player.is_playing else _player._video.play()

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

    @property
    def timeline(self):
        return self._time

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

    @property
    def video(self):
        return self._player.value

    @video.setter
    def video(self, value):
        self._player.value = value
        self._player.enabled = value is not None
        if value:
            self._time.max = self._player.max

    @property
    def project(self):
        return self._project
Beispiel #2
0
class VideoPlayer(BaseWidget):
    def __init__(self):
        super(VideoPlayer, self).__init__('Video Player')

        #Defnition of the form fields

        #         self._dirname = ControlText('Directory', 'Default Value')
        self._button_play = ControlButton("Play")
        self._button_play.value = self.__play_all

        self._button_pause = ControlButton("Pause")
        self._button_pause.value = self.__pause_all

        self._button_refresh = ControlButton("Reload")
        self._button_refresh.value = self.__refresh_all

        self._button_print = ControlButton("Print")
        self._button_print.value = self.__print_value
        #         self.formset = [{'Tab1':['_dirname'],},'_button']

        #         self._directory = ControlDir('Choose a directory')
        self._file1 = ControlFile('File 1')
        self._file2 = ControlFile('File 2')
        #         print(self._file.value)
        self._filetree = ControlFilesTree('Choose a file')

        #         self._filetree.value = 'C:\\Users\\Ashwini Naik\\Videos\\Captures'

        #         self._checkbox = ControlCheckBox('Choose a directory')
        #         self._checkboxList = ControlCheckBoxList('Choose a file')
        self._player = ControlPlayer('Choose a file')
        self._player1 = ControlPlayer('Choose a file')
        #         self._slider = ControlSlider('Slider')

        self._player.value = '_file.value'
        #         self._player.refresh()
        self.formset = [('_button_play', '_button_pause', '_button_refresh'),
                        ('_file1', '_file2'), ('_player', '_player1')]
#         self._control.changed_event = self.__print_value

    def __print_value(self):
        print("Player 1" + self._player.value)
        print("Player 2" + self._player1.value)
        print("File 1" + self._file1.value)
        print("File 2" + self._file2.value)

    def __play_all(self):

        self._player.show()
        self._player.value = self._file1.value

        self._player1.show()
        self._player1.value = self._file2.value

        self._player.play()
        self._player1.play()

    def __pause_all(self):
        self._player.stop()
        self._player1.stop()

    def __refresh_all(self):
        self._player.value = self._file1.value
        self._player1.value = self._file2.value
Beispiel #3
0
class QuadView(BaseWidget):
    def __init__(self, *args, **kwargs):
        super().__init__('4-Cam')

        self.set_margin(10)

        # Definition of the forms fields
        self._player1 = ControlPlayer('Player1')
        self._player2 = ControlPlayer('Player2')
        self._player3 = ControlPlayer('Player3')
        self._player4 = ControlPlayer('Player4')
        self._runbutton = ControlButton('Stop')
        self._screenshot = ControlButton('Screenshot')
        self._outputfile = ControlDir('Screenshots Ausgabe Ordner')
        self._cams = ControlCheckBoxList('Kameras')

        # Define the event that will be called when the run button is processed
        self._runbutton.value = self.__stopEvent
        self._screenshot.value = self._saveImages

        self.__check_all_avaliable_cameras()

        self.formset = [{
            '0-Kameras': [('_runbutton'), ('_player1', '_player2'),
                          ('_player3', '_player4')],
            '1-Einstellungen': [('_outputfile'), ('_cams')]
        }]

        self._player1.value = self.__assign_capture(0)
        self._player2.value = self.__assign_capture(1)
        self._player3.value = self.__assign_capture(2)
        self._player4.value = self.__assign_capture(3)

        self._outputfile.value = os.getcwd()

        self.__runEvent()

    def __assign_capture(self, player_id):
        checked_cam_ids = self._cams.checked_indexes
        if checked_cam_ids.__len__() > player_id:
            return cv2.VideoCapture(checked_cam_ids[player_id])
        return cv2.VideoCapture()

    def __runEvent(self):
        """
        After setting the best parameters run the full algorithm
        """
        self._player1.update_frame()
        self._player1.play()
        self._player2.update_frame()
        self._player2.play()
        self._player3.update_frame()
        self._player3.play()
        self._player4.update_frame()
        self._player4.play()
        pass

    def __stopEvent(self):
        self._player1.stop()
        self._player2.stop()
        self._player3.stop()
        self._player4.stop()

    def _saveImages(self):
        """
        Saves the Images of all cams to a file
        :return:
        """
        currentTime = str(strftime("%Y-%m-%d_%H:%M:%S", gmtime()))
        cv2.imwrite(
            os.path.join(self._outputfile.value, currentTime + '_cam_1.png'),
            self._player1.value['frame'])
        cv2.imwrite(
            os.path.join(self._outputfile.value, currentTime + '_cam_2.png'),
            self._player2.value['frame'])
        cv2.imwrite(
            os.path.join(self._outputfile.value, currentTime + '_cam_3.png'),
            self._player3.value['frame'])
        cv2.imwrite(
            os.path.join(self._outputfile.value, currentTime + '_cam_4.png'),
            self._player4.value['frame'])
        print("Written screenshots to disk")
        pass

    def accessible_device(self, source):
        cap = cv2.VideoCapture(source)
        if cap is None or not cap.isOpened():
            return False
        cap.release()
        return True

    def __check_all_avaliable_cameras(self):
        for x in range(0, 10):
            isCam = self.accessible_device(x)
            if isCam:
                self._cams += ('Kamera ' + str(x), True)
Beispiel #4
0
class BaseModule(BaseWidget):
    """Application form"""
    def __init__(self):
        global conf
        conf += 'pythonvideoannotator.resources'  # Resources can only be loaded after pyqt is running

        super(BaseModule, self).__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.formset = ['_player']

        self._dock.value = self._time
        self._player.process_frame_event = self.process_frame_event
        self._player.click_event = self.on_player_click_event
        self._time.key_release_event = self.__timeline_key_release_event

        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]
                new_version_numbers = [int(x) for x in new_version.split('.')]
                version_numbers = [int(x) for x in __version__.split('.')]
                for new_n, n in zip(new_version_numbers, version_numbers):
                    if new_n > n:
                        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()
                        break
            else:
                print('Enabled to check new versions')

        except Exception as e:
            print('Enabled to check new versions:')

    ######################################################################################
    #### FUNCTIONS #######################################################################
    ######################################################################################

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

        if conf.CHART_FILE_PATH: self._time.import_chart(*conf.CHART_FILE_PATH)
        if conf.PROJECT_PATH: self.load_project(conf.PROJECT_PATH)

    ######################################################################################
    #### IO FUNCTIONS ####################################################################
    ######################################################################################

    def save(self, data, project_path=None):
        self._project.save(data, project_path)
        return data

    def load(self, data, project_path=None):
        try:
            self._project.load(data, project_path)
        except FileNotFoundError as e:
            QMessageBox.critical(self, "Error", str(e))

    def save_project(self, project_path=None):
        try:
            if project_path is None:
                project_path = QFileDialog.getExistingDirectory(
                    self, "Select the project directory")

            if project_path is not None and str(project_path) != '':
                project_path = str(project_path)
                self.save({}, project_path)
        except Exception as e:
            QMessageBox.critical(self, "Error", str(e))

    def load_project(self, project_path=None):
        if project_path is None:
            project_path = QFileDialog.getExistingDirectory(
                self, "Select the project directory")
        if project_path is not None and str(project_path) != '':
            self.load({}, str(project_path))

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

    def on_player_click_event(self, event, x, y):
        """
        Code to select a blob with the mouse
        """
        super(VideoAnnotationEditor, self).on_player_click_event(event, x, y)
        self._player.refresh()

    def process_frame_event(self, frame):
        """
        Function called before render each frame
        """
        return frame

    def add_dataset_event(self, dataset):
        pass

    def removed_dataset_event(self, dataset):
        pass

    def removed_object_event(self, obj):
        pass

    def __open_project_event(self):
        self.load_project()

    def __save_project_event(self):
        print('Project saved')
        self.save_project(self._project.directory)

    def __save_project_as_event(self):
        self.save_project()

    def __timeline_key_release_event(self, event):
        """
        Control video playback using the space bar to Play/Pause
        """
        if event.key() == QtCore.Qt.Key_Space:
            self._player.stop(
            ) if self._player.is_playing else _player._video.play()

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

    @property
    def timeline(self):
        return self._time

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

    @property
    def video(self):
        return self._player.value

    @video.setter
    def video(self, value):
        self._player.value = value
        self._player.enabled = value is not None
        if value:
            self._time.max = self._player.max

    @property
    def project(self):
        return self._project
Beispiel #5
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()
Beispiel #6
0
class VideoWindow(BaseWidget):

    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

    def __videoFileSelect(self, filepath):
        try:
            self._videofile.value = str(filepath)
            self._player.value = self._videofile.value
            self._player.refresh()
            self._player.update_frame()
            # Hazard set to occur for 60 frames upon flagging
            self._hazard_default_duration = int(self._player.fps * 2)
            self._video_loaded = True
        except Exception as e:
            self.__updateStatus("Unable to select video")

    def __videoFileSelectionEvent(self):
        """
        When the videofile is selected instantiate the video in the player
        """
        try:
            self._player.value = self._videofile.value
            # Hazard set to occur for 60 frames upon flagging
            self._hazard_default_duration = int(self._player.fps * 2)
            self._video_loaded = True
        except Exception as e:
            self.__updateStatus("No video selected")

    def __nextVideo(self):
        if self._current_video >= (self._video_count - 1):
            self.__updateStatus("No more videos")
        else:
            self._current_video += 1
            self.__reset()
            self.__videoFileSelect(self._file_list[self._current_video])
            self._progress.value = self._current_video + 1

    def __reset(self):
        self._player.stop()
        self.__saveData()
        print("saving on reset")
        self._timeline.clean()
        self.__updateStatus("")

    def __processFrame(self, frame):
        """
        Do some processing to the frame and return the result frame
        """
        return frame

    def __clickEvent(self, click_event, x, y):
        self.__labelHazard()

    def __tagEvent(self, event):
        """
        Label hazard using Enter key
        """
        key = event.key()

        # QtCore.Qt.Key_Enter gives wrong value (at least on test PC) for Enter key
        # Desired == 16777221, actual == 16777220

        key_id = 16777220

        if event.key() == key_id:
            self.__labelHazard()

    def __addFlag(self, value):
        self._timeline.add_period(value)

    def __labelHazard(self):
        if self._video_loaded:
            if self._player.video_index > (self._player.max - self._hazard_default_duration):
                flag_duration = round(self._player.max - self._player.video_index)
            else:
                flag_duration = self._hazard_default_duration
            try:
                self._hazard_counter += 1
                self.__updateStatus("Hazard flagged! | Frame: {} Timestamp: {}".format(self._player.video_index,
                                round(self._player.video_index/self._player.fps, 3)))
                self.__addFlag((self._player.video_index, self._player.video_index + flag_duration, str(self._hazard_counter)))
            except Exception as e:
                try:
                    self._player.refresh()
                    self.__updateStatus("Hazard flagged! | Frame: {} Timestamp: {}".format(self._player.video_index,
                                    round(self._player.video_index/self._player.fps, 3)))
                except Exception as e:
                    self.__updateStatus("Unable to label, exiting...")
                    sys.exit(0)

    def __saveData(self):
        self._timeline.export_csv_file(self._videofile.value + "_hazard.csv")
        self.__updateStatus("Saving {} to {}".format(self._videofile.value + "_hazard.csv", self._args["dest"]))

    def __updateStatus(self, msg):
        self._status.value = str(msg)