Пример #1
0
    def __init__(self):
        super(MainWindow, self).__init__()
        # self.setGeometry(5,60,700,500)

        self.setWindowTitle('Video Processing')
        self.background_color = self.palette().color(QtGui.QPalette.Background)

        # if os.name is 'posix':  # is a mac or linux
        #     scriptDir = os.path.dirname(sys.argv[0])
        # else:  # is a  windows
        #     scriptDir = os.getcwd()

        # This is the main Window
        self.main_Widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.main_Widget)

        # Elements of the main window
        # image viewer
        self.displayImage = ImageViewer()

        # Menu bar __ Top - Main options
        self.menuBar = QtWidgets.QMenuBar(self)
        self.setStyleSheet("""
                                   QMenuBar {
                                   font-size:18px;
                                   background : transparent;
                                   }
                                   """)
        # Tool bar __ Top - Functions to analyze the current image
        self.toolBar_Top = QtWidgets.QToolBar(self)

        # Tool bar __ Bottom  - Play/pause buttons
        self.toolBar_Bottom = QtWidgets.QToolBar(self)

        # Frame Slider _ Bottom  - Easily move between frames
        self.slider_Bottom = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_Bottom.setMinimum(1)
        self.slider_Bottom.setMaximum(100)
        self.slider_Bottom.setValue(1)
        self.slider_Bottom.setTickInterval(1)
        self.slider_Bottom.setEnabled(False)
        self.slider_Bottom.valueChanged.connect(self.slidervaluechange)

        # Status Bar _ Bottom - Show the current frame number
        self.frameLabel = QtWidgets.QLabel('')
        self.frameLabel.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom = QtWidgets.QStatusBar()
        self.statusBar_Bottom.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom.addPermanentWidget(self.frameLabel)

        # Definition of Variables
        self.video_handler = None
        self.video_name = None  # name and location of video file
        self.current_frame = 0  # what is the current frame
        self.timer = QtCore.QTimer()  # controls video playback

        # initialize the User Interface
        self.initUI()
        self.show()
Пример #2
0
class ShowExample(QtWidgets.QMainWindow):
    def __init__(self):
        super(ShowExample, self).__init__()
        
        self.setWindowTitle('Example')
        #self._new_window = None

        
        
        if os.name is 'posix': #is a mac or linux
            scriptDir = os.path.dirname(sys.argv[0])
        else: #is a  windows 
                scriptDir = os.getcwd()
                
        img_Qt = QtGui.QImage(scriptDir + os.path.sep + 'include' +os.path.sep +'icons'+ os.path.sep + 'Facial-Nerve-Center.jpg')
        pixmap = QtGui.QPixmap.fromImage(img_Qt)
        self._view_photo = ImageViewer()
        self._view_photo.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(230,230,230)))
        self._view_photo.setPhoto(pixmap)
        
        
        self.label_title = QtWidgets.QLabel()
        self.label_title.setText('Sample text')
        self.label_title.setWordWrap(True) 
        self.label_title.setFont(QtGui.QFont("Times",weight=QtGui.QFont.Bold))
        
        self.label_content = QtWidgets.QLabel()
        self.label_content .setText('Sample text')
        self.label_content .setWordWrap(True) 
        #self.label.setMaximumWidth(500)
        
        
        self.main_Widget = QtWidgets.QWidget(self)
        
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.label_title)
        layout.addWidget(self.label_content)
        layout.addWidget(self._view_photo)

        self.main_Widget.setLayout(layout)
        self.setCentralWidget(self.main_Widget)
Пример #3
0
class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        # self.setGeometry(5,60,700,500)

        self.setWindowTitle('Video Processing')
        self.background_color = self.palette().color(QtGui.QPalette.Background)

        # if os.name is 'posix':  # is a mac or linux
        #     scriptDir = os.path.dirname(sys.argv[0])
        # else:  # is a  windows
        #     scriptDir = os.getcwd()

        # This is the main Window
        self.main_Widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.main_Widget)

        # Elements of the main window
        # image viewer
        self.displayImage = ImageViewer()

        # Menu bar __ Top - Main options
        self.menuBar = QtWidgets.QMenuBar(self)
        self.setStyleSheet("""
                                   QMenuBar {
                                   font-size:18px;
                                   background : transparent;
                                   }
                                   """)
        # Tool bar __ Top - Functions to analyze the current image
        self.toolBar_Top = QtWidgets.QToolBar(self)

        # Tool bar __ Bottom  - Play/pause buttons
        self.toolBar_Bottom = QtWidgets.QToolBar(self)

        # Frame Slider _ Bottom  - Easily move between frames
        self.slider_Bottom = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_Bottom.setMinimum(1)
        self.slider_Bottom.setMaximum(100)
        self.slider_Bottom.setValue(1)
        self.slider_Bottom.setTickInterval(1)
        self.slider_Bottom.setEnabled(False)
        self.slider_Bottom.valueChanged.connect(self.slidervaluechange)

        # Status Bar _ Bottom - Show the current frame number
        self.frameLabel = QtWidgets.QLabel('')
        self.frameLabel.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom = QtWidgets.QStatusBar()
        self.statusBar_Bottom.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom.addPermanentWidget(self.frameLabel)

        # Definition of Variables
        self.video_handler = None
        self.video_name = None  # name and location of video file
        self.current_frame = 0  # what is the current frame
        self.timer = QtCore.QTimer()  # controls video playback

        # initialize the User Interface
        self.initUI()
        self.show()

    def initUI(self):

        # Populate the different menus
        file_menu = self.menuBar.addMenu("&File")

        load_video = file_menu.addAction("Load Video File")
        load_video.setShortcut("Ctrl+F")
        load_video.setStatusTip('Load video file, accepted formats : .mp4, .avi, .mov')
        load_video.triggered.connect(self.openvideofile)

        load_landmarks = file_menu.addAction("Load Landmarks File")
        load_landmarks.setShortcut("Ctrl+L")
        load_landmarks.setStatusTip('Load landmark file, accepted formats : .csv')
        # load_landmarks.triggered.connect(self.load_file)

        quit_program = file_menu.addAction("Quit")
        quit_program.setShortcut("Ctrl+Q")
        # quit_program.triggered.connect(self.load_file)

        video_menu = self.menuBar.addMenu("&Video")
        play_video = video_menu.addAction("Play Video")
        play_video.setShortcut("Ctrl+P")
        play_video.setStatusTip('Play video at given playback speed')
        # play_video.triggered.connect(self.load_file)

        stop_video = video_menu.addAction("Stop Video")
        stop_video.setShortcut("Ctrl+S")
        stop_video.setStatusTip('Stop video playback')
        # stop_video.triggered.connect(self.load_file)

        jump_to_frame = video_menu.addAction("Jump to Frame")
        jump_to_frame.setShortcut("Ctrl+J")
        jump_to_frame.setStatusTip('Jump to certain frame')
        # jump_to_frame.triggered.connect(self.load_file)

        playback_settings = video_menu.addAction("Playback Settings")
        playback_settings.setShortcut("Ctrl+P")
        playback_settings.setStatusTip('Define video playback settings')
        # playback_settings.triggered.connect(self.load_file)

        landmarks_menu = self.menuBar.addMenu("&Landmarks")
        # process_current_frame = landmarks_menu.addAction("Process Current Frame")
        # process_current_frame.setShortcut("Ctrl+C")
        # process_current_frame.setStatusTip('Determine facial landmarks for current frame')
        # # process_current_frame.triggered.connect(self.load_file)

        process_some_frame = landmarks_menu.addAction("Process Frames")
        process_some_frame.setShortcut("Ctrl+S")
        process_some_frame.setStatusTip('Determine facial landmarks for some frames in the video')
        # process_some_frame.triggered.connect(self.load_file)

        process_all_frame = landmarks_menu.addAction("Process All Frames")
        process_all_frame.setShortcut("Ctrl+A")
        process_all_frame.setStatusTip('Determine facial landmarks for all frames in the video')
        # process_all_frame.triggered.connect(self.load_file)

        process_settings = landmarks_menu.addAction("Process Frames Settings")
        process_settings.setShortcut("Ctrl+L")
        process_settings.setStatusTip('Determine facial landmarks for all frames in the video')
        # process_settings.triggered.connect(self.load_file)

        # fill the top toolbar

        process_current_frame =  QtWidgets.QAction('Process current frame', self)
        process_current_frame.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # process_current_frame.connect(self.match_iris)

        toggle_landmark = QtWidgets.QAction('Show/Hide facial landmarks', self)
        toggle_landmark.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # toggle_landmark.connect(self.match_iris)

        manual_adjustment = QtWidgets.QAction('Manually adjust landmarks position in current frame', self)
        manual_adjustment.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # manual_adjustment.connect(self.match_iris)

        landmark_settings = QtWidgets.QAction('Adjust landmark visualization settings', self)
        landmark_settings.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # landmark_settings.connect(self.match_iris)

        show_metrics = QtWidgets.QAction('Display facial metrics in current frame', self)
        show_metrics.setIcon(QtGui.QIcon('./icons/facial-metrics.png'))
        # show_metrics.connect(self.match_iris)

        snapshot = QtWidgets.QAction('Save snapshot of current view', self)
        snapshot.setIcon(QtGui.QIcon('./icons/profile.png'))
        # snapshot.connect(self.match_iris)

        self.toolBar_Top.addActions((process_current_frame, toggle_landmark, manual_adjustment, landmark_settings, show_metrics, snapshot))
        self.toolBar_Top.setIconSize(QtCore.QSize(50, 50))
        for action in self.toolBar_Top.actions():
            widget = self.toolBar_Top.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar_Top.setMinimumSize(self.toolBar_Top.sizeHint())
        self.toolBar_Top.setStyleSheet('QToolBar{spacing:8px;}')

        # fill the bottom toolbar
        play_action = QtWidgets.QAction('Play', self)
        play_action.setShortcut('Shift+S')
        play_action.setIcon(QtGui.QIcon('./icons/play-arrow.png'))
        play_action.triggered.connect(self.playvideo)

        stop_action = QtWidgets.QAction('Stop', self)
        stop_action.setShortcut('Shift+Z')
        stop_action.setIcon(QtGui.QIcon('./icons/pause.png'))
        stop_action.triggered.connect(self.stopvideo)

        fastforward_action = QtWidgets.QAction('Fast Forward', self)
        fastforward_action.setShortcut('Shift+D')
        fastforward_action.setIcon(QtGui.QIcon('./icons/fast-forward.png'))
        # fastforward_action.triggered.connect(self.match_iris)

        rewind_action = QtWidgets.QAction('Rewind', self)
        rewind_action.setShortcut('Shift+A')
        rewind_action.setIcon(QtGui.QIcon('./icons/rewind.png'))
        # rewind_action.triggered.connect(self.match_iris)

        # spacer widget for left
        left_spacer = QtWidgets.QWidget(self)
        left_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        # spacer widget for right
        right_spacer = QtWidgets.QWidget(self)
        right_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

        # fill the bottom toolbar
        self.toolBar_Bottom.addWidget(left_spacer)
        self.toolBar_Bottom.addActions((rewind_action, play_action, stop_action, fastforward_action))
        self.toolBar_Bottom.addWidget(right_spacer)
        self.toolBar_Bottom.setIconSize(QtCore.QSize(35, 35))
        # for action in self.toolBar_Bottom.actions():
        #     widget = self.toolBar_Bottom.widgetForAction(action)
        #     widget.setFixedSize(35, 35)

        self.toolBar_Bottom.setMinimumSize(self.toolBar_Bottom.sizeHint())
        self.toolBar_Bottom.setStyleSheet('QToolBar{spacing:8px;}')

        # Create the layout

        # The main window has 6 components in the following order:
        # Menu Bar - Tool Bar - Image viewer - Tool Bar - Slider - Status Bar

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.menuBar)
        layout.addWidget(self.toolBar_Top)
        layout.addWidget(self.displayImage)
        layout.addWidget(self.toolBar_Bottom)
        layout.addWidget(self.slider_Bottom)
        self.setStatusBar(self.statusBar_Bottom)

        # Set the defined layout in the main window
        self.main_Widget.setLayout(layout)
        
        self.setGeometry(300, 100, 600, 800)

    def openvideofile(self):
        # load a file using the widget
        name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Video File',
            '', "Video files (*.mp4 *.avi *.mov *.MP4 *.AVI *.MOV)")

        if not name:
            pass
        else:
            
            name = os.path.normpath(name)
            # change window name to match the file name
            self.setWindowTitle('Video Processing - ' + name.split(os.path.sep)[-1])

            # self.video_handler = VideoHandler(name)
            # image = self.video_handler.readfirstframe()
            # self.displayImage._opencvimage = image
            # self.displayImage.update_view()
            # # update the frame number
            # self.current_frame = 0
            # # put the frame information in the app
            # self.frameLabel.setText('Frame :'+str(int(self.current_frame)+1)+'/'+str(self.video_handler.video_length))
            # # update the slider
            # self.slider_Bottom.setMinimum(1)
            # self.slider_Bottom.setMaximum(self.video_handler.video_length)
            # self.slider_Bottom.blockSignals(True)
            # self.slider_Bottom.setValue(1)
            # self.slider_Bottom.blockSignals(False)
            # self.slider_Bottom.setEnabled(True)

            
#            name = os.path.normpath(name)
#            # Remove previous video handlers to avoid taking odd frames
#            self.video_handle = None
#            # change window name to match the file name
#            self.setWindowTitle('Video Processing - ' + name.split(os.path.sep)[-1])
#
#            # user provided a video, open it using OpenCV
        video_handler = cv2.VideoCapture(name)  # read the video
        success, image = video_handler.read()  # get the first frame

        if success:  # if the frame exists then show the image
            self.displayImage._opencvimage = image
            self.displayImage.update_view()
            num_frames = int(video_handler.get(cv2.CAP_PROP_FRAME_COUNT))
            video_length = num_frames
            video_fps = int(video_handler.get(cv2.CAP_PROP_FPS))
            video_fps = video_fps
            self.current_frame = 0
            # put the frame information in the app
            self.frameLabel.setText('Frame :'+str(int(self.current_frame)+1)+'/'+str(video_length))
            # update the slider
            self.slider_Bottom.setMinimum(1)
            self.slider_Bottom.setMaximum(video_length)
            self.slider_Bottom.blockSignals(True)
            self.slider_Bottom.setValue(1)
            self.slider_Bottom.blockSignals(False)
            self.slider_Bottom.setEnabled(True)
        video_handler.release()

    def playvideo(self):
        # verify that the video handler is not empty
        if self.video_handler is not None:

            self.timer.timeout.connect(self.nextframefunction)
            self.timer.start(1000.0/self.video_handler.playbackspeed)



    def nextframefunction(self):
        # verify that we are not at the last frame
        if self.current_frame <= self.video_handler.video_length - 1:
            # verify the there are frames in the frames in the queue
            if self.video_handler.more():
                image = self.video_handler.read()
                self.displayImage._opencvimage = image
                self.displayImage.update_view()
                self.current_frame += 1
                # put the frame information in the app
                self.frameLabel.setText(
                    'Frame :' + str(int(self.current_frame) + 1) + '/' + str(self.video_handler.video_length))
                # update the slider
                self.slider_Bottom.blockSignals(True)
                self.slider_Bottom.setValue(self.current_frame + 1)
                self.slider_Bottom.blockSignals(False)
            else:
                # finished the video
                self.timer.stop()
        else:
            # reached the end of the video
            self.timer.stop()

    @pyqtSlot
    def putframe(self,image):



        
        # # verify that we are not in the last frame
        # if self.current_frame <= self.video_length - 1:
        #     success, image = self.video_handle.read()
        #     if success:
        #         # if the frame exists then show the image
        #         self.displayImage._opencvimage = image
        #         self.displayImage.update_view()
        #         # update the frame number at the bottom of the app
        #         self.frameLabel.setText('Frame : ' + str(int(self.current_frame)+1) + '/' + str(self.video_length))
        #         # update the slider
        #         self.slider_Bottom.blockSignals(True)
        #         self.slider_Bottom.setValue(self.current_frame + 1)
        #         self.slider_Bottom.blockSignals(False)
        #         # update frame number
        #         self.current_frame += 1.
        #     else: # if it doens't then stop the time
        #         self.timer.stop()
        #
        # else:  # reached the end of the video
        #     self.timer.stop()

    def stopvideo(self):
        # stop video if video is playing
        if self.timer.isActive():  # verify is the video is running
            # activate slider and stop playback

            self.video_handler.stop()
            self.timer.stop()


    def slidervaluechange(self):
        pass
        # slider_value = self.slider_Bottom.value()
        # self.video_handle.set(cv2.CAP_PROP_POS_FRAMES, slider_value)
        # success, image = self.video_handle.read()
        # if success:
        #     # if the frame exists then show the image
        #     self.displayImage._opencvimage = image
        #     self.displayImage.update_view()
        #     # update the frame number at the bottom of the app
        #     self.frameLabel.setText('Frame : ' + str(int(self.current_frame) + 1) + '/' + str(self.video_length))
        #     # update frame number
        #     self.current_frame = slider_value



if __name__ == '__main__':
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"
    freeze_support()

    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()

    app.setStyle(QtWidgets.QStyleFactory.create('Cleanlooks'))

    GUI = MainWindow()
    GUI.show()
    app.exec_()
Пример #4
0
class Emotrics(QtWidgets.QDialog):
    def __init__(self, FileName):
        super(Emotrics, self).__init__()
        #self.setGeometry(5,60,700,500)
        self.setWindowTitle('Emotrics')
        scriptDir = os.path.dirname(os.path.realpath(sys.argv[0]))
        self.setWindowIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'meei_3WR_icon.ico'))
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowMinMaxButtonsHint)

        self._new_window = None
        self._file_name = FileName
        self._Patient = None
        self._tab1_results = None
        self._tab2_results = None
        self._tab3_results = None
        self._toggle_landmaks = True
        self._toggle_lines = True

        self._Scale = 1  #this variable carries the scale of the image if it
        #needs to be resized, if Scale = 1 then the origina
        #image was used for processing. If Scale > 1 then
        #the original image was too large and a resized image
        #was used for processing

        # create Thread  to take care of the landmarks and iris estimation
        self.thread_landmarks = QtCore.QThread()  # no parent!

        #initialize the User Interface
        self.initUI()

    def initUI(self):
        #local directory
        scriptDir = os.getcwd(
        )  #os.path.dirname(os.path.realpath(sys.argv[0]))

        #image
        #read the image from file
        #img_Qt = QtGui.QImage(scriptDir + os.path.sep + 'include' +os.path.sep +'icon_color'+ os.path.sep + 'Facial-Nerve-Center.jpg')
        #img_show = QtGui.QPixmap.fromImage(img_Qt)

        #the image will be displayed in the custom ImageViewer
        self.displayImage = ImageViewer()
        #self.displayImage.setPhoto(img_show)

        #toolbar
        fitAction = QtWidgets.QAction('Fit image to window', self)
        fitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'fit_to_size_icon.png'))
        fitAction.triggered.connect(self.displayImage.show_entire_image)

        eyeAction = QtWidgets.QAction('Match iris diameter', self)
        eyeAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon.png'))
        eyeAction.triggered.connect(self.match_iris)

        eyeLoad = QtWidgets.QAction('Import iris position and diameter', self)
        eyeLoad.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon_import.png'))
        eyeLoad.triggered.connect(self.load_iris)

        centerAction = QtWidgets.QAction('Find face center', self)
        centerAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'center_icon.png'))
        centerAction.triggered.connect(self.face_center)

        toggleAction = QtWidgets.QAction('Toggle landmarks', self)
        toggleAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'toggle-icon.png'))
        toggleAction.triggered.connect(self.toggle_landmarks)

        measuresAction = QtWidgets.QAction('Facial metrics', self)
        measuresAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'ruler_icon.png'))
        measuresAction.triggered.connect(self.create_new_window)

        saveAction = QtWidgets.QAction('Save results', self)
        saveAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'save_icon.png'))
        saveAction.triggered.connect(self.save_results)

        snapshotAction = QtWidgets.QAction('Save current view', self)
        snapshotAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'snapshot_icon.png'))
        snapshotAction.triggered.connect(self.save_snapshot)

        exitAction = QtWidgets.QAction('Exit', self)
        exitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'exit_icon.png'))
        exitAction.triggered.connect(self.close_app)

        #create the toolbar and add the actions
        self.toolBar = QtWidgets.QToolBar(self)
        self.toolBar.addActions(
            (fitAction, eyeAction, eyeLoad, centerAction, toggleAction,
             measuresAction, snapshotAction, saveAction, exitAction))

        #set the size of each icon to 50x50
        self.toolBar.setIconSize(QtCore.QSize(50, 50))

        for action in self.toolBar.actions():
            widget = self.toolBar.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar.setMinimumSize(self.toolBar.sizeHint())
        self.toolBar.setStyleSheet('QToolBar{spacing:5px;}')

        #the main window consist of the toolbar and the ImageViewer
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolBar)
        layout.addWidget(self.displayImage)
        self.setLayout(layout)

        self.load_file(self._file_name)
        self.displayImage.update_view()
        self.show()

    def create_new_window(self):
        #this creates a new window to display all the facial metrics, there
        #are two modes, one if there is no Patient (self._Patient = None)
        #and another if there is a patient (two photos)
        if self._Patient is None:

            if self.displayImage._shape is not None:
                #if the measurements window is already open then close it
                if self._new_window is not None:
                    self._new_window.close()
                    self._new_window = None

                #compute the facial metrics using the landmarks
                MeasurementsLeft, MeasurementsRight, MeasurementsDeviation, MeasurementsPercentual = get_measurements_from_data(
                    self.displayImage._shape, self.displayImage._lefteye,
                    self.displayImage._righteye)

                #send all the information the the appropiate places in the window
                self._tab1_results = CustomTabResult()

                #filling t_new_window_tab1_results he info for the right
                self._tab1_results._CE_right.setText('{0:.2f}'.format(
                    MeasurementsRight.CommissureExcursion))
                self._tab1_results._SA_right.setText('{0:.2f}'.format(
                    MeasurementsRight.SmileAngle))
                self._tab1_results._DS_right.setText('{0:.2f}'.format(
                    MeasurementsRight.DentalShow))
                self._tab1_results._MRD1_right.setText('{0:.2f}'.format(
                    MeasurementsRight.MarginalReflexDistance1))
                self._tab1_results._MRD2_right.setText('{0:.2f}'.format(
                    MeasurementsRight.MarginalReflexDistance2))
                self._tab1_results._BH_right.setText('{0:.2f}'.format(
                    MeasurementsRight.BrowHeight))

                #filling the info for the left
                self._tab1_results._CE_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.CommissureExcursion))
                self._tab1_results._SA_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.SmileAngle))
                self._tab1_results._DS_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.DentalShow))
                self._tab1_results._MRD1_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.MarginalReflexDistance1))
                self._tab1_results._MRD2_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.MarginalReflexDistance2))
                self._tab1_results._BH_left.setText('{0:.2f}'.format(
                    MeasurementsLeft.BrowHeight))

                #deviation
                self._tab1_results._CE_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommissureExcursion))
                self._tab1_results._SA_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.SmileAngle))
                self._tab1_results._MRD1_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance1))
                self._tab1_results._MRD2_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance2))
                self._tab1_results._BH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.BrowHeight))
                self._tab1_results._DS_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.DentalShow))
                self._tab1_results._CH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommisureHeightDeviation))
                self._tab1_results._UVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.UpperLipHeightDeviation))
                self._tab1_results._LVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.LowerLipHeightDeviation))

                self._tab1_results._CE_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.CommissureExcursion))
                self._tab1_results._SA_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.SmileAngle))
                self._tab1_results._MRD1_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance1))
                self._tab1_results._MRD2_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance2))
                self._tab1_results._BH_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.BrowHeight))
                self._tab1_results._DS_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.DentalShow))

                delimiter = os.path.sep
                temp = self._file_name.split(delimiter)
                photo_name = temp[-1]
                photo_name = photo_name[0:-4]
                self._tab1_results._tab_name = photo_name

                #say to the window that presents the results that there is only 1 tab
                self._new_window = ShowResults(self._tab1_results)
                #show the window with the results
                self._new_window.show()
                self.displayImage.update_view()

        else:
            #here there is a patient and so the result window will have three tabs
            if (self._Patient.FirstPhoto._shape
                    is not None) and (self._Patient.SecondPhoto._shape
                                      is not None):
                #if the measurements window is already open then close it
                if self._new_window is not None:
                    self._new_window.close()
                    self._new_window = None

                #compute the facial metrics for the first photo and fill the information
                MeasurementsLeftFirst, MeasurementsRightFirst, MeasurementsDeviation, MeasurementsPercentual = get_measurements_from_data(
                    self._Patient.FirstPhoto._shape,
                    self._Patient.FirstPhoto._lefteye,
                    self._Patient.FirstPhoto._righteye)

                self._tab1_results = CustomTabResult()

                #filling t_new_window_tab1_results he info for the right
                self._tab1_results._CE_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.CommissureExcursion))
                self._tab1_results._SA_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.SmileAngle))
                self._tab1_results._DS_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.DentalShow))
                self._tab1_results._MRD1_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.MarginalReflexDistance1))
                self._tab1_results._MRD2_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.MarginalReflexDistance2))
                self._tab1_results._BH_right.setText('{0:.2f}'.format(
                    MeasurementsRightFirst.BrowHeight))

                #filling the info for the left
                self._tab1_results._CE_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.CommissureExcursion))
                self._tab1_results._SA_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.SmileAngle))
                self._tab1_results._DS_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.DentalShow))
                self._tab1_results._MRD1_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.MarginalReflexDistance1))
                self._tab1_results._MRD2_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.MarginalReflexDistance2))
                self._tab1_results._BH_left.setText('{0:.2f}'.format(
                    MeasurementsLeftFirst.BrowHeight))

                #deviation
                self._tab1_results._CE_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommissureExcursion))
                self._tab1_results._SA_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.SmileAngle))
                self._tab1_results._MRD1_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance1))
                self._tab1_results._MRD2_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance2))
                self._tab1_results._BH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.BrowHeight))
                self._tab1_results._DS_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.DentalShow))
                self._tab1_results._CH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommisureHeightDeviation))
                self._tab1_results._UVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.UpperLipHeightDeviation))
                self._tab1_results._LVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.LowerLipHeightDeviation))

                self._tab1_results._CE_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.CommissureExcursion))
                self._tab1_results._SA_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.SmileAngle))
                self._tab1_results._MRD1_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance1))
                self._tab1_results._MRD2_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance2))
                self._tab1_results._BH_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.BrowHeight))
                self._tab1_results._DS_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.DentalShow))

                self._tab1_results._tab_name = self._Patient.FirstPhoto._ID

                #compute the facial metrics for the second photo and fill the information
                MeasurementsLeftSecond, MeasurementsRightSecond, MeasurementsDeviation, MeasurementsPercentual = get_measurements_from_data(
                    self._Patient.SecondPhoto._shape,
                    self._Patient.SecondPhoto._lefteye,
                    self._Patient.SecondPhoto._righteye)

                self._tab2_results = CustomTabResult()

                #filling t_new_window_tab1_results he info for the right
                self._tab2_results._CE_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.CommissureExcursion))
                self._tab2_results._SA_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.SmileAngle))
                self._tab2_results._DS_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.DentalShow))
                self._tab2_results._MRD1_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.MarginalReflexDistance1))
                self._tab2_results._MRD2_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.MarginalReflexDistance2))
                self._tab2_results._BH_right.setText('{0:.2f}'.format(
                    MeasurementsRightSecond.BrowHeight))

                #filling the info for the left
                self._tab2_results._CE_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.CommissureExcursion))
                self._tab2_results._SA_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.SmileAngle))
                self._tab2_results._DS_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.DentalShow))
                self._tab2_results._MRD1_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.MarginalReflexDistance1))
                self._tab2_results._MRD2_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.MarginalReflexDistance2))
                self._tab2_results._BH_left.setText('{0:.2f}'.format(
                    MeasurementsLeftSecond.BrowHeight))

                #deviation
                self._tab2_results._CE_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommissureExcursion))
                self._tab2_results._SA_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.SmileAngle))
                self._tab2_results._MRD1_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance1))
                self._tab2_results._MRD2_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.MarginalReflexDistance2))
                self._tab2_results._BH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.BrowHeight))
                self._tab2_results._DS_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.DentalShow))
                self._tab2_results._CH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.CommisureHeightDeviation))
                self._tab2_results._UVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.UpperLipHeightDeviation))
                self._tab2_results._LVH_dev.setText('{0:.2f}'.format(
                    MeasurementsDeviation.LowerLipHeightDeviation))

                self._tab2_results._CE_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.CommissureExcursion))
                self._tab2_results._SA_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.SmileAngle))
                self._tab2_results._MRD1_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance1))
                self._tab2_results._MRD2_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.MarginalReflexDistance2))
                self._tab2_results._BH_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.BrowHeight))
                self._tab2_results._DS_dev_p.setText('{0:.2f}'.format(
                    MeasurementsPercentual.DentalShow))

                self._tab2_results._tab_name = self._Patient.SecondPhoto._ID

                #compute the the different between both photos and fill the information
                self._tab3_results = CustomTabResult()

                #filling tab3_results with the difference between the two photos
                self._tab3_results._CE_right.setText('{0:.2f}'.format(
                    -MeasurementsRightFirst.CommissureExcursion +
                    MeasurementsRightSecond.CommissureExcursion))
                self._tab3_results._SA_right.setText(
                    '{0:.2f}'.format(-MeasurementsRightFirst.SmileAngle +
                                     MeasurementsRightSecond.SmileAngle))
                self._tab3_results._DS_right.setText(
                    '{0:.2f}'.format(-MeasurementsRightFirst.DentalShow +
                                     MeasurementsRightSecond.DentalShow))
                self._tab3_results._MRD1_right.setText('{0:.2f}'.format(
                    -MeasurementsRightFirst.MarginalReflexDistance1 +
                    MeasurementsRightSecond.MarginalReflexDistance1))
                self._tab3_results._MRD2_right.setText('{0:.2f}'.format(
                    -MeasurementsRightFirst.MarginalReflexDistance2 +
                    MeasurementsRightSecond.MarginalReflexDistance2))
                self._tab3_results._BH_right.setText(
                    '{0:.2f}'.format(-MeasurementsRightFirst.BrowHeight +
                                     MeasurementsRightSecond.BrowHeight))

                #filling the info for the left
                self._tab3_results._CE_left.setText('{0:.2f}'.format(
                    -MeasurementsLeftFirst.CommissureExcursion +
                    MeasurementsLeftSecond.CommissureExcursion))
                self._tab3_results._SA_left.setText(
                    '{0:.2f}'.format(-MeasurementsLeftFirst.SmileAngle +
                                     MeasurementsLeftSecond.SmileAngle))
                self._tab3_results._DS_left.setText(
                    '{0:.2f}'.format(-MeasurementsLeftFirst.DentalShow +
                                     MeasurementsLeftSecond.DentalShow))
                self._tab3_results._MRD1_left.setText('{0:.2f}'.format(
                    -MeasurementsLeftFirst.MarginalReflexDistance1 +
                    MeasurementsLeftSecond.MarginalReflexDistance1))
                self._tab3_results._MRD2_left.setText('{0:.2f}'.format(
                    -MeasurementsLeftFirst.MarginalReflexDistance2 +
                    MeasurementsLeftSecond.MarginalReflexDistance2))
                self._tab3_results._BH_left.setText(
                    '{0:.2f}'.format(-MeasurementsLeftFirst.BrowHeight +
                                     MeasurementsLeftSecond.BrowHeight))

                #say to the window that presents the results that there are 3 tabs
                self._new_window = ShowResults(self._tab1_results,
                                               self._tab2_results,
                                               self._tab3_results)
                #show the window with the results
                self._new_window.show()

    def match_iris(self):
        #make both iris have the same diameter as the bigger one
        if self.displayImage._lefteye is not None:
            if self.displayImage._lefteye[2] < self.displayImage._righteye[2]:
                self.displayImage._lefteye[2] = self.displayImage._righteye[2]
            elif self.displayImage._lefteye[2] > self.displayImage._righteye[2]:
                self.displayImage._righteye[2] = self.displayImage._lefteye[2]
            elif self.displayImage._lefteye[2] == self.displayImage._righteye[
                    2]:
                pass

            self._toggle_lines = True
            self.displayImage._points = None
            self.displayImage.set_update_photo()

    def face_center(self):
        #find a line connecting the center of both iris and then fit a perperdicular
        #line in the middle
        if self.displayImage._shape is not None:

            if self._toggle_lines == True:
                self._toggle_lines = False
                points = estimate_lines(self.displayImage._opencvimage,
                                        self.displayImage._lefteye,
                                        self.displayImage._righteye)
                self.displayImage._points = points
                self.displayImage.set_update_photo()
            else:
                self.displayImage._points = None
                self.displayImage.set_update_photo()
                self._toggle_lines = True

    def load_file(self, name):

        #        #load a file using the widget
        #        name,_ = QtWidgets.QFileDialog.getOpenFileName(
        #                self,'Load Image',
        #                '',"Image files (*.png *.jpg *.jpeg *.tif *.tiff *.PNG *.JPG *.JPEG *.TIF *.TIFF)")
        #
        #        if not name:
        #            pass
        #        else:
        #the user will load an single image so get rid of Patient and the
        # changephotoAction in the toolbar
        self._Patient = None

        #if windows then transform / to \ (python stuffs)
        name = os.path.normpath(name)
        self._file_name = name
        #if the measurements window is open then close it
        if self._new_window is not None:
            self._new_window.close()
        #load image
        self.displayImage._opencvimage = cv2.imread(name)

        #if the photo was already processed then get the information for the
        #txt file, otherwise process the photo using the landmark ans pupil
        #localization algorithms
        file_txt = name[:-4]
        file_txt = (file_txt + '.txt')
        if os.path.isfile(file_txt):
            shape, lefteye, righteye, boundingbox = get_info_from_txt(file_txt)
            self.displayImage._lefteye = lefteye
            self.displayImage._righteye = righteye
            self.displayImage._shape = shape
            self.displayImage._boundingbox = boundingbox
            self.displayImage._points = None
            self.displayImage.update_view()
        else:
            #if the image is too large then it needs to be resized....
            h, w, d = self.displayImage._opencvimage.shape

            #if the image is too big then we need to resize it so that the landmark
            #localization process can be performed in a reasonable time
            self._Scale = 1  #start from a clear initial scale
            if h > 1500 or w > 1500:
                if h >= w:
                    h_n = 1500
                    self._Scale = h / h_n
                    w_n = int(np.round(w / self._Scale, 0))
                    #self.displayImage._opencvimage=cv2.resize(self.displayImage._opencvimage, (w_n, h_n), interpolation=cv2.INTER_AREA)
                    temp_image = cv2.resize(self.displayImage._opencvimage,
                                            (w_n, h_n),
                                            interpolation=cv2.INTER_AREA)
                    #self._image = image
                else:
                    w_n = 1500
                    self._Scale = w / w_n
                    h_n = int(np.round(h / self._Scale, 0))
                    #self.displayImage._opencvimage=cv2.resize(self.displayImage._opencvimage, (w_n, h_n), interpolation=cv2.INTER_AREA)
                    temp_image = cv2.resize(self.displayImage._opencvimage,
                                            (w_n, h_n),
                                            interpolation=cv2.INTER_AREA)
                    #self._image = image

#                    #now that the image has been reduced, ask the user if the image
#                    #should be saved for continue the processing, otherwise the
#                    #processing cannot continue with the large image
#
#                    #get the image name (separete it from the path)
#                    delimiter = os.path.sep
#                    split_name=name.split(delimiter)
#
#                    #the variable 'name' contains the file name and the path, we now
#                    #get the file name and assign it to the photo object
#                    file_name = split_name[-1]
#                    new_file_name = file_name[:-4]+'_small.png'
#
#                    choice = QtWidgets.QMessageBox.information(self, 'Large Image',
#                            'The image is too large to process.\n\nPressing OK will create a new file\n%s\nin the current folder. This file will be used for processing.\nOtherwise, click Close to finalize the App.'%new_file_name,
#                            QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Close, QtWidgets.QMessageBox.Ok)
#
#                    if choice == QtWidgets.QMessageBox.Close :
#                        self.close()
#                        app.exec_()
#                    else:
#                        #create a new, smaller image and use that for processing
#                        name = name[:-4]+'_small.png'
#                        self._file_name = name
#                        cv2.imwrite(name,self.displayImage._opencvimage)
            else:
                #the image is of appropiate dimensions so no need for modification
                temp_image = self.displayImage._opencvimage.copy()
                #pass

            #get the landmarks using dlib, and the and the iris
            #using Dougman's algorithm
            #This is done in a separate thread to prevent the gui from
            #freezing and crashing

            #create worker, pass the image to the worker
            #self.landmarks = GetLandmarks(self.displayImage._opencvimage)
            self.landmarks = GetLandmarks(temp_image)
            #move worker to new thread
            self.landmarks.moveToThread(self.thread_landmarks)
            #start the new thread where the landmark processing will be performed
            self.thread_landmarks.start()
            #Connect Thread started signal to Worker operational slot method
            self.thread_landmarks.started.connect(self.landmarks.getlandmarks)
            #connect signal emmited by landmarks to a function
            self.landmarks.landmarks.connect(self.ProcessShape)
            #define the end of the thread
            self.landmarks.finished.connect(self.thread_landmarks.quit)

    def ProcessShape(self, shape, numFaces, lefteye, righteye, boundingbox):
        if numFaces == 1:

            if self._Scale is not 1:  #in case that a smaller image was used for
                #processing, then update the landmark
                #position with the scale factor
                for k in range(0, 68):
                    shape[k] = [
                        int(np.round(shape[k, 0] * self._Scale, 0)),
                        int(np.round(shape[k, 1] * self._Scale, 0))
                    ]

                for k in range(0, 3):
                    lefteye[k] = int(np.round(lefteye[k] * self._Scale, 0))
                    righteye[k] = int(np.round(righteye[k] * self._Scale, 0))

                for k in range(0, 4):
                    boundingbox[k] = int(
                        np.round(boundingbox[k] * self._Scale, 0))

            self.displayImage._shape = shape
            self.displayImage._lefteye = lefteye
            self.displayImage._righteye = righteye
            self.displayImage._boundingbox = boundingbox

            #
            self.displayImage._points = None
        elif numFaces == 0:
            #no face in image then shape is None
            self.displayImage._shape = None
            #inform the user
            QtWidgets.QMessageBox.warning(
                self, "Warning",
                "No face in the image.\nIf the image does contain a face plase modify the brightness and try again.",
                QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)
        elif numFaces > 1:
            #multiple faces in image then shape is None
            self.displayImage._shape = None
            #inform the user
            QtWidgets.QMessageBox.warning(
                self, "Warning",
                "Multiple faces in the image.\nPlease load an image with a single face.",
                QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)

        self.displayImage.update_view()

    def load_iris(self):
        #load a file using the widget
        name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Iris Position and Diameter', '',
            "Image files (*.png *.jpg *.jpeg *.tif *.tiff *.PNG *.JPG *.JPEG *.TIF *.TIFF)"
        )

        if not name:
            pass
        else:
            #if windows then transform / to \ (python stuffs)
            name = os.path.normpath(name)
            #if the measurements window is open then close it, the measures will be updated with the new eyes position
            if self._new_window is not None:
                self._new_window.close()

            #if the photo was already processed then get the information for the
            #txt file, otherwise process the photo using the landmark ans pupil
            #localization algorithms
            file_txt = name[:-4]
            file_txt = (file_txt + '.txt')
            if os.path.isfile(file_txt):
                shape, lefteye, righteye, _ = get_info_from_txt(file_txt)

                dx_left = lefteye[0] - shape[27, 0]
                dy_left = shape[27, 1] - lefteye[1]

                dx_right = shape[27, 0] - righteye[0]
                dy_right = shape[27, 1] - righteye[1]

                self.displayImage._lefteye = [
                    self.displayImage._shape[27, 0] + dx_left,
                    self.displayImage._shape[27, 1] - dy_left, lefteye[2]
                ]
                self.displayImage._righteye = [
                    self.displayImage._shape[27, 0] - dx_right,
                    self.displayImage._shape[27, 1] - dy_right, lefteye[2]
                ]
                self.displayImage.set_update_photo()

            else:
                QtWidgets.QMessageBox.warning(
                    self, "Warning",
                    "Iris information for this photograph is not avaliable",
                    QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)


#                self.displayImage._lefteye = lefteye
#                self.displayImage._righteye = righteye
#                self.displayImage.set_update_photo()

    def toggle_landmarks(self):
        #Hide - show the landmarks
        if self._toggle_landmaks is True:
            self._toggle_landmaks = False
            self.displayImage.set_update_photo(self._toggle_landmaks)
        elif self._toggle_landmaks is False:
            self._toggle_landmaks = True
            self.displayImage.set_update_photo(self._toggle_landmaks)

    def save_snapshot(self):
        #save the current view
        if self.displayImage._opencvimage is not None:
            proposed_name = self._file_name[:-4] + '-landmarks'
            name, _ = QtWidgets.QFileDialog.getSaveFileName(
                self, 'Save File', proposed_name,
                'png (*.png);;jpg (*.jpg);; jpeg (*.jpeg)')
            if not name:
                pass
            else:
                #if shape then add shape to image
                temp_image = self.displayImage._opencvimage.copy()

                #draw 68 landmark points
                if self.displayImage._shape is not None:
                    temp_image = mark_picture(temp_image,
                                              self.displayImage._shape,
                                              self.displayImage._lefteye,
                                              self.displayImage._righteye,
                                              self.displayImage._points)

                save_snaptshot_to_file(temp_image, name)

    def save_results(self):
        #save the results in a txt and xls files. There are two modes, one if
        #there is no patient and another is the is a patient (two photos)
        if self._Patient is None:  #this implies that there is a single photo
            if self._file_name is not None:
                if self.displayImage._shape is not None:
                    save_txt_file(self._file_name, self.displayImage._shape,
                                  self.displayImage._lefteye,
                                  self.displayImage._righteye,
                                  self.displayImage._boundingbox)
                    MeasurementsLeft, MeasurementsRight, MeasurementsDeviation, MeasurementsPercentual = get_measurements_from_data(
                        self.displayImage._shape, self.displayImage._lefteye,
                        self.displayImage._righteye)
                    save_xls_file(self._file_name, MeasurementsLeft,
                                  MeasurementsRight, MeasurementsDeviation,
                                  MeasurementsPercentual)
        else:  #this implies that the user created a patient and wants to analize two photos
            save_txt_file(self._Patient.FirstPhoto._file_name,
                          self._Patient.FirstPhoto._shape,
                          self._Patient.FirstPhoto._lefteye,
                          self._Patient.FirstPhoto._righteye,
                          self._Patient.FirstPhoto._boundingbox)
            save_txt_file(self._Patient.SecondPhoto._file_name,
                          self._Patient.SecondPhoto._shape,
                          self._Patient.SecondPhoto._lefteye,
                          self._Patient.SecondPhoto._righteye,
                          self._Patient.SecondPhoto._boundingbox)
            save_xls_file_patient(self._file_name, self._Patient)

    def close_app(self):

        #ask is the user really wants to close the app
        choice = QtWidgets.QMessageBox.question(
            self, 'Message', 'Do you want to exit?',
            QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
            QtWidgets.QMessageBox.No)

        if choice == QtWidgets.QMessageBox.Yes:
            self.close()
            app.exec_()
        else:
            pass

    def closeEvent(self, event):
        #we need to close all the windows before closing the program
        if self._new_window is not None:
            self._new_window.close()
        event.accept()
Пример #5
0
    def initUI(self):
        #local directory
        scriptDir = os.getcwd(
        )  #os.path.dirname(os.path.realpath(sys.argv[0]))

        #image
        #read the image from file
        #img_Qt = QtGui.QImage(scriptDir + os.path.sep + 'include' +os.path.sep +'icon_color'+ os.path.sep + 'Facial-Nerve-Center.jpg')
        #img_show = QtGui.QPixmap.fromImage(img_Qt)

        #the image will be displayed in the custom ImageViewer
        self.displayImage = ImageViewer()
        #self.displayImage.setPhoto(img_show)

        #toolbar
        fitAction = QtWidgets.QAction('Fit image to window', self)
        fitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'fit_to_size_icon.png'))
        fitAction.triggered.connect(self.displayImage.show_entire_image)

        eyeAction = QtWidgets.QAction('Match iris diameter', self)
        eyeAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon.png'))
        eyeAction.triggered.connect(self.match_iris)

        eyeLoad = QtWidgets.QAction('Import iris position and diameter', self)
        eyeLoad.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon_import.png'))
        eyeLoad.triggered.connect(self.load_iris)

        centerAction = QtWidgets.QAction('Find face center', self)
        centerAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'center_icon.png'))
        centerAction.triggered.connect(self.face_center)

        toggleAction = QtWidgets.QAction('Toggle landmarks', self)
        toggleAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'toggle-icon.png'))
        toggleAction.triggered.connect(self.toggle_landmarks)

        measuresAction = QtWidgets.QAction('Facial metrics', self)
        measuresAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'ruler_icon.png'))
        measuresAction.triggered.connect(self.create_new_window)

        saveAction = QtWidgets.QAction('Save results', self)
        saveAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'save_icon.png'))
        saveAction.triggered.connect(self.save_results)

        snapshotAction = QtWidgets.QAction('Save current view', self)
        snapshotAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'snapshot_icon.png'))
        snapshotAction.triggered.connect(self.save_snapshot)

        exitAction = QtWidgets.QAction('Exit', self)
        exitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'exit_icon.png'))
        exitAction.triggered.connect(self.close_app)

        #create the toolbar and add the actions
        self.toolBar = QtWidgets.QToolBar(self)
        self.toolBar.addActions(
            (fitAction, eyeAction, eyeLoad, centerAction, toggleAction,
             measuresAction, snapshotAction, saveAction, exitAction))

        #set the size of each icon to 50x50
        self.toolBar.setIconSize(QtCore.QSize(50, 50))

        for action in self.toolBar.actions():
            widget = self.toolBar.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar.setMinimumSize(self.toolBar.sizeHint())
        self.toolBar.setStyleSheet('QToolBar{spacing:5px;}')

        #the main window consist of the toolbar and the ImageViewer
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolBar)
        layout.addWidget(self.displayImage)
        self.setLayout(layout)

        self.load_file(self._file_name)
        self.displayImage.update_view()
        self.show()
Пример #6
0
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # self.setGeometry(5,60,700,500)

        self.setWindowTitle('Video Processing')
        self.background_color = self.palette().color(QtGui.QPalette.Background)

        # if os.name is 'posix':  # is a mac or linux
        #     scriptDir = os.path.dirname(sys.argv[0])
        # else:  # is a  windows
        #     scriptDir = os.getcwd()

        # This is the main Window
        self.main_Widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.main_Widget)

        # Elements of the main window
        # image viewer
        self.displayImage = ImageViewer()

        # Menu bar __ Top - Main options
        self.menuBar = QtWidgets.QMenuBar(self)
        self.setStyleSheet("""
                                   QMenuBar {
                                   font-size:18px;
                                   background : transparent;
                                   }
                                   """)
        # Tool bar __ Top - Functions to analyze the current image
        self.toolBar_Top = QtWidgets.QToolBar(self)

        # Tool bar __ Bottom  - Play/pause buttons
        self.toolBar_Bottom = QtWidgets.QToolBar(self)

        # Frame Slider _ Bottom  - Easily move between frames
        self.slider_Bottom = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_Bottom.setMinimum(1)
        self.slider_Bottom.setMaximum(100)
        self.slider_Bottom.setValue(1)
        self.slider_Bottom.setTickInterval(1)
        self.slider_Bottom.setEnabled(False)
        self.slider_Bottom.valueChanged.connect(self.slidervaluechange)
        self.slider_Bottom.sliderReleased.connect(self.slidervaluefinal)

        # Status Bar _ Bottom - Show the current frame number
        self.frameLabel = QtWidgets.QLabel('')
        self.frameLabel.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom = QtWidgets.QStatusBar()
        self.statusBar_Bottom.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom.addPermanentWidget(self.frameLabel)

        # Definition of Variables
        self.video_handler = None
        self.video_name = None  # name and location of video file
        self.current_frame = 0  # what is the current frame
        self.timer = QtCore.QTimer()  # controls video playback
        self.jump_frames = 1  # number of frames to jump with fastforward or rewind buttons

        # initialize the User Interface
        self.initUI()
        self.show()

    def initUI(self):

        # Populate the different menus
        file_menu = self.menuBar.addMenu("&File")

        load_video = file_menu.addAction("Load Video File")
        load_video.setShortcut("Ctrl+F")
        load_video.setStatusTip(
            'Load video file, accepted formats : .mp4, .avi, .mov')
        load_video.triggered.connect(self.openvideofile)

        load_landmarks = file_menu.addAction("Load Landmarks File")
        load_landmarks.setShortcut("Ctrl+L")
        load_landmarks.setStatusTip(
            'Load landmark file, accepted formats : .csv')
        # load_landmarks.triggered.connect(self.load_file)

        quit_program = file_menu.addAction("Quit")
        quit_program.setShortcut("Ctrl+Q")
        # quit_program.triggered.connect(self.load_file)

        video_menu = self.menuBar.addMenu("&Video")
        play_video = video_menu.addAction("Play Video")
        play_video.setShortcut("Ctrl+P")
        play_video.setStatusTip('Play video at given playback speed')
        # play_video.triggered.connect(self.load_file)

        stop_video = video_menu.addAction("Stop Video")
        stop_video.setShortcut("Ctrl+S")
        stop_video.setStatusTip('Stop video playback')
        # stop_video.triggered.connect(self.load_file)

        jump_to_frame = video_menu.addAction("Jump to Frame")
        jump_to_frame.setShortcut("Ctrl+J")
        jump_to_frame.setStatusTip('Jump to certain frame')
        # jump_to_frame.triggered.connect(self.load_file)

        playback_settings = video_menu.addAction("Playback Settings")
        playback_settings.setShortcut("Ctrl+P")
        playback_settings.setStatusTip('Define video playback settings')
        # playback_settings.triggered.connect(self.load_file)

        landmarks_menu = self.menuBar.addMenu("&Landmarks")
        # process_current_frame = landmarks_menu.addAction("Process Current Frame")
        # process_current_frame.setShortcut("Ctrl+C")
        # process_current_frame.setStatusTip('Determine facial landmarks for current frame')
        # # process_current_frame.triggered.connect(self.load_file)

        process_some_frame = landmarks_menu.addAction("Process Frames")
        process_some_frame.setShortcut("Ctrl+S")
        process_some_frame.setStatusTip(
            'Determine facial landmarks for some frames in the video')
        # process_some_frame.triggered.connect(self.load_file)

        process_all_frame = landmarks_menu.addAction("Process All Frames")
        process_all_frame.setShortcut("Ctrl+A")
        process_all_frame.setStatusTip(
            'Determine facial landmarks for all frames in the video')
        # process_all_frame.triggered.connect(self.load_file)

        process_settings = landmarks_menu.addAction("Process Frames Settings")
        process_settings.setShortcut("Ctrl+L")
        process_settings.setStatusTip(
            'Determine facial landmarks for all frames in the video')
        # process_settings.triggered.connect(self.load_file)

        # fill the top toolbar

        process_current_frame = QtWidgets.QAction('Process current frame',
                                                  self)
        process_current_frame.setIcon(
            QtGui.QIcon('./icons/facial-analysis.png'))
        # process_current_frame.connect(self.match_iris)

        toggle_landmark = QtWidgets.QAction('Show/Hide facial landmarks', self)
        toggle_landmark.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # toggle_landmark.connect(self.match_iris)

        manual_adjustment = QtWidgets.QAction(
            'Manually adjust landmarks position in current frame', self)
        manual_adjustment.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # manual_adjustment.connect(self.match_iris)

        landmark_settings = QtWidgets.QAction(
            'Adjust landmark visualization settings', self)
        landmark_settings.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # landmark_settings.connect(self.match_iris)

        show_metrics = QtWidgets.QAction(
            'Display facial metrics in current frame', self)
        show_metrics.setIcon(QtGui.QIcon('./icons/facial-metrics.png'))
        # show_metrics.connect(self.match_iris)

        snapshot = QtWidgets.QAction('Save snapshot of current view', self)
        snapshot.setIcon(QtGui.QIcon('./icons/profile.png'))
        # snapshot.connect(self.match_iris)

        self.toolBar_Top.addActions(
            (process_current_frame, toggle_landmark, manual_adjustment,
             landmark_settings, show_metrics, snapshot))
        self.toolBar_Top.setIconSize(QtCore.QSize(50, 50))
        for action in self.toolBar_Top.actions():
            widget = self.toolBar_Top.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar_Top.setMinimumSize(self.toolBar_Top.sizeHint())
        self.toolBar_Top.setStyleSheet('QToolBar{spacing:8px;}')

        # fill the bottom toolbar
        play_action = QtWidgets.QAction('Play', self)
        play_action.setShortcut('Shift+S')
        play_action.setIcon(QtGui.QIcon('./icons/play-arrow.png'))
        play_action.triggered.connect(self.playvideo)
        #play_action.setToolTip(self, 'FPS ='+str(self.video_handler.playbackspeed))

        stop_action = QtWidgets.QAction('Stop', self)
        stop_action.setShortcut('Shift+Z')
        stop_action.setIcon(QtGui.QIcon('./icons/pause.png'))
        stop_action.triggered.connect(self.stopvideo)

        fastforward_action = QtWidgets.QAction('Fast Forward', self)
        fastforward_action.setShortcut('Shift+D')
        fastforward_action.setIcon(QtGui.QIcon('./icons/fast-forward.png'))
        fastforward_action.triggered.connect(self.fastforward)

        rewind_action = QtWidgets.QAction('Rewind', self)
        rewind_action.setShortcut('Shift+A')
        rewind_action.setIcon(QtGui.QIcon('./icons/rewind.png'))
        rewind_action.triggered.connect(self.rewind)

        # spacer widget for left
        left_spacer = QtWidgets.QWidget(self)
        left_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)
        # spacer widget for right
        right_spacer = QtWidgets.QWidget(self)
        right_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                   QtWidgets.QSizePolicy.Expanding)

        # fill the bottom toolbar
        self.toolBar_Bottom.addWidget(left_spacer)
        self.toolBar_Bottom.addActions(
            (rewind_action, play_action, stop_action, fastforward_action))
        self.toolBar_Bottom.addWidget(right_spacer)
        self.toolBar_Bottom.setIconSize(QtCore.QSize(35, 35))
        # for action in self.toolBar_Bottom.actions():
        #     widget = self.toolBar_Bottom.widgetForAction(action)
        #     widget.setFixedSize(35, 35)

        self.toolBar_Bottom.setMinimumSize(self.toolBar_Bottom.sizeHint())
        self.toolBar_Bottom.setStyleSheet('QToolBar{spacing:8px;}')

        # Create the layout

        # The main window has 6 components in the following order:
        # Menu Bar - Tool Bar - Image viewer - Tool Bar - Slider - Status Bar

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.menuBar)
        layout.addWidget(self.toolBar_Top)
        layout.addWidget(self.displayImage)
        layout.addWidget(self.toolBar_Bottom)
        layout.addWidget(self.slider_Bottom)
        self.setStatusBar(self.statusBar_Bottom)

        # Set the defined layout in the main window
        self.main_Widget.setLayout(layout)

        self.setGeometry(300, 100, 600, 800)

    def openvideofile(self):
        # load a file using the widget
        name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Video File', '',
            "Video files (*.mp4 *.avi *.mov *.MP4 *.AVI *.MOV)")

        if not name:
            pass
        else:

            name = os.path.normpath(name)
            # Remove previous video handlers to avoid taking odd frames
            self.video_handler = None
            # change window name to match the file name
            self.setWindowTitle('Video Processing - ' +
                                name.split(os.path.sep)[-1])

            # user provided a video, open it using OpenCV
            self.video_handler = VideoInformation(name)  # read the video
            success, image = self.video_handler.read()  # get the first frame
            if success:  # if the frame exists then show the image
                # video was successfully loaded and will be presented to the user, now we will verify if a csv file with
                # with the same name as the video exits. This file should contain the landmark and bounding box
                # information
                cvs_file_name = name[:-3] + 'csv'
                if os.path.exists(cvs_file_name):
                    self.video_handler.video_landmarks_filename = cvs_file_name
                    try:
                        self.video_handler.video_landmarks_DF = pd.read_csv(
                            self.video_handler.video_landmarks_filename)
                        # self.video_handler.video_landmarks_DF.set_index('Frame_number', inplace=True)
                    except ValueError:
                        QtWidgets.QMessageBox.critical(
                            0, "Error",
                            "Landmark file appears to exist but cannot be loaded"
                        )
                        self.video_handler.video_landmarks_filename = None
                        self.video_handler.video_landmarks_DF = None

                self.updateviewer(image, 0)
                self.slider_Bottom.setMinimum(1)
                self.slider_Bottom.setMaximum(self.video_handler.video_length)
                self.slider_Bottom.setEnabled(True)

    def playvideo(self):
        # verify that the video handler is not empty
        if self.video_handler is not None:
            self.timer.timeout.connect(self.nextframefunction)
            self.timer.start(1000.0 / self.video_handler.playbackspeed)

    def nextframefunction(self):
        # verify that we are not at the last frame
        if self.current_frame <= self.video_handler.video_length:
            success, image = self.video_handler.read()  # get a new frame
            if success:
                frame_number = self.current_frame + 1
                self.updateviewer(image, frame_number)
        else:
            # reached the end of the video
            self.timer.stop()

    def stopvideo(self):
        # stop video if video is playing
        if self.timer.isActive():  # verify is the video is running
            self.timer.stop()

    def fastforward(self):

        if self.timer.isActive():  # verify is the video is running
            # top video playback before moving slider
            self.timer.stop()

        next_frame = self.current_frame + self.jump_frames
        if next_frame > self.video_handler.video_length - 1:
            next_frame = self.video_handler.video_length - 1
            pass
        else:
            self.video_handler.video_handler.set(cv2.CAP_PROP_POS_FRAMES,
                                                 next_frame)
            success, image = self.video_handler.read()
            if success:
                self.updateviewer(image, next_frame)
            else:
                print(next_frame, self.current_frame)

    def rewind(self):

        if self.timer.isActive():  # verify is the video is running
            # top video playback before moving slider
            self.timer.stop()

        previous_frame = self.current_frame - self.jump_frames
        if previous_frame < 0:
            previous_frame = 0
            pass
        else:
            self.video_handler.video_handler.set(cv2.CAP_PROP_POS_FRAMES,
                                                 previous_frame)
            success, image = self.video_handler.read()
            if success:
                self.updateviewer(image, previous_frame)

    def updateviewer(self, image, frame_number):
        self.displayImage._opencvimage = image
        if self.video_handler.video_landmarks_DF is not None:
            try:
                frame_information = self.video_handler.video_landmarks_DF.loc[
                    self.video_handler.video_landmarks_DF['Frame_number'] ==
                    frame_number].values
            except ValueError:
                frame_information = []

            if len(frame_information) > 0:
                shape = np.array([frame_information[0][6:]])
                shape = np.reshape(shape.astype(np.int), (-1, 2))
                self.displayImage._shape = shape

        self.displayImage.update_view()
        self.current_frame = frame_number
        self.frameLabel.setText('Frame : ' + str(int(self.current_frame) + 1) +
                                '/' + str(self.video_handler.video_length))

        self.slider_Bottom.blockSignals(True)
        self.slider_Bottom.setValue(frame_number + 1)
        self.slider_Bottom.blockSignals(False)

    def slidervaluechange(self):
        if self.timer.isActive():  # verify is the video is running
            # top video playback before moving slider
            self.timer.stop()

        # get slider position and update frame number
        slider_position = self.slider_Bottom.value()
        self.current_frame = slider_position - 1
        self.frameLabel.setText('Frame : ' + str(int(self.current_frame) + 1) +
                                '/' + str(self.video_handler.video_length))

        self.is_slider_moving = True

    def slidervaluefinal(self):
        # adjust view only when the slider reaches its final position
        self.video_handler.video_handler.set(cv2.CAP_PROP_POS_FRAMES,
                                             self.current_frame)
        success, image = self.video_handler.read()
        if success:
            self.updateviewer(image, self.current_frame)
class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        # self.setGeometry(5,60,700,500)

        self.setWindowTitle('Video Processing')
        self.background_color = self.palette().color(QtGui.QPalette.Background)

        # if os.name is 'posix':  # is a mac or linux
        #     scriptDir = os.path.dirname(sys.argv[0])
        # else:  # is a  windows
        #     scriptDir = os.getcwd()

        # This is the main Window
        self.main_Widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.main_Widget)

        # Elements of the main window
        # image viewer
        self.displayImage = ImageViewer()

        # Menu bar __ Top - Main options
        self.menuBar = QtWidgets.QMenuBar(self)
        self.setStyleSheet("""
                                   QMenuBar {
                                   font-size:18px;
                                   background : transparent;
                                   }
                                   """)
        # Tool bar __ Top - Functions to analyze the current image
        self.toolBar_Top = QtWidgets.QToolBar(self)

        # Tool bar __ Bottom  - Play/pause buttons
        self.toolBar_Bottom = QtWidgets.QToolBar(self)

        # Frame Slider _ Bottom  - Easily move between frames
        self.slider_Bottom = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_Bottom.setMinimum(1)
        self.slider_Bottom.setMaximum(100)
        self.slider_Bottom.setValue(1)
        self.slider_Bottom.setTickInterval(1)
        self.slider_Bottom.setEnabled(False)
        self.slider_Bottom.valueChanged.connect(self.slidervaluechange)

        # Status Bar _ Bottom - Show the current frame number
        self.frameLabel = QtWidgets.QLabel('')
        self.frameLabel.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom = QtWidgets.QStatusBar()
        self.statusBar_Bottom.setFont(QtGui.QFont("Times", 10))
        self.statusBar_Bottom.addPermanentWidget(self.frameLabel)

        # Definition of Variables
        self.video_handler = None
        self.video_name = None  # name and location of video file
        self.current_frame = 0  # what is the current frame
        self.timer = QtCore.QTimer()  # controls video playback

        # threads used to process data and help in the visualization
        self.thread_slider = QThread() # no parent
        self.class_slider = UpdateSlider()

        # initialize the User Interface
        self.initUI()
        self.show()

    def initUI(self):

        # Populate the different menus
        file_menu = self.menuBar.addMenu("&File")

        load_video = file_menu.addAction("Load Video File")
        load_video.setShortcut("Ctrl+F")
        load_video.setStatusTip('Load video file, accepted formats : .mp4, .avi, .mov')
        load_video.triggered.connect(self.openvideofile)

        load_landmarks = file_menu.addAction("Load Landmarks File")
        load_landmarks.setShortcut("Ctrl+L")
        load_landmarks.setStatusTip('Load landmark file, accepted formats : .csv')
        # load_landmarks.triggered.connect(self.load_file)

        quit_program = file_menu.addAction("Quit")
        quit_program.setShortcut("Ctrl+Q")
        # quit_program.triggered.connect(self.load_file)

        video_menu = self.menuBar.addMenu("&Video")
        play_video = video_menu.addAction("Play Video")
        play_video.setShortcut("Ctrl+P")
        play_video.setStatusTip('Play video at given playback speed')
        # play_video.triggered.connect(self.load_file)

        stop_video = video_menu.addAction("Stop Video")
        stop_video.setShortcut("Ctrl+S")
        stop_video.setStatusTip('Stop video playback')
        # stop_video.triggered.connect(self.load_file)

        jump_to_frame = video_menu.addAction("Jump to Frame")
        jump_to_frame.setShortcut("Ctrl+J")
        jump_to_frame.setStatusTip('Jump to certain frame')
        # jump_to_frame.triggered.connect(self.load_file)

        playback_settings = video_menu.addAction("Playback Settings")
        playback_settings.setShortcut("Ctrl+P")
        playback_settings.setStatusTip('Define video playback settings')
        # playback_settings.triggered.connect(self.load_file)

        landmarks_menu = self.menuBar.addMenu("&Landmarks")
        # process_current_frame = landmarks_menu.addAction("Process Current Frame")
        # process_current_frame.setShortcut("Ctrl+C")
        # process_current_frame.setStatusTip('Determine facial landmarks for current frame')
        # # process_current_frame.triggered.connect(self.load_file)

        process_some_frame = landmarks_menu.addAction("Process Frames")
        process_some_frame.setShortcut("Ctrl+S")
        process_some_frame.setStatusTip('Determine facial landmarks for some frames in the video')
        # process_some_frame.triggered.connect(self.load_file)

        process_all_frame = landmarks_menu.addAction("Process All Frames")
        process_all_frame.setShortcut("Ctrl+A")
        process_all_frame.setStatusTip('Determine facial landmarks for all frames in the video')
        # process_all_frame.triggered.connect(self.load_file)

        process_settings = landmarks_menu.addAction("Process Frames Settings")
        process_settings.setShortcut("Ctrl+L")
        process_settings.setStatusTip('Determine facial landmarks for all frames in the video')
        # process_settings.triggered.connect(self.load_file)

        # fill the top toolbar

        process_current_frame =  QtWidgets.QAction('Process current frame', self)
        process_current_frame.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # process_current_frame.connect(self.match_iris)

        toggle_landmark = QtWidgets.QAction('Show/Hide facial landmarks', self)
        toggle_landmark.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # toggle_landmark.connect(self.match_iris)

        manual_adjustment = QtWidgets.QAction('Manually adjust landmarks position in current frame', self)
        manual_adjustment.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # manual_adjustment.connect(self.match_iris)

        landmark_settings = QtWidgets.QAction('Adjust landmark visualization settings', self)
        landmark_settings.setIcon(QtGui.QIcon('./icons/facial-analysis.png'))
        # landmark_settings.connect(self.match_iris)

        show_metrics = QtWidgets.QAction('Display facial metrics in current frame', self)
        show_metrics.setIcon(QtGui.QIcon('./icons/facial-metrics.png'))
        # show_metrics.connect(self.match_iris)

        snapshot = QtWidgets.QAction('Save snapshot of current view', self)
        snapshot.setIcon(QtGui.QIcon('./icons/profile.png'))
        # snapshot.connect(self.match_iris)

        self.toolBar_Top.addActions((process_current_frame, toggle_landmark, manual_adjustment, landmark_settings, show_metrics, snapshot))
        self.toolBar_Top.setIconSize(QtCore.QSize(50, 50))
        for action in self.toolBar_Top.actions():
            widget = self.toolBar_Top.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar_Top.setMinimumSize(self.toolBar_Top.sizeHint())
        self.toolBar_Top.setStyleSheet('QToolBar{spacing:8px;}')

        # fill the bottom toolbar
        play_action = QtWidgets.QAction('Play', self)
        play_action.setShortcut('Shift+S')
        play_action.setIcon(QtGui.QIcon('./icons/play-arrow.png'))
        play_action.triggered.connect(self.playvideo)

        stop_action = QtWidgets.QAction('Stop', self)
        stop_action.setShortcut('Shift+Z')
        stop_action.setIcon(QtGui.QIcon('./icons/pause.png'))
        stop_action.triggered.connect(self.stopvideo)

        fastforward_action = QtWidgets.QAction('Fast Forward', self)
        fastforward_action.setShortcut('Shift+D')
        fastforward_action.setIcon(QtGui.QIcon('./icons/fast-forward.png'))
        # fastforward_action.triggered.connect(self.match_iris)

        rewind_action = QtWidgets.QAction('Rewind', self)
        rewind_action.setShortcut('Shift+A')
        rewind_action.setIcon(QtGui.QIcon('./icons/rewind.png'))
        # rewind_action.triggered.connect(self.match_iris)

        # spacer widget for left
        left_spacer = QtWidgets.QWidget(self)
        left_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        # spacer widget for right
        right_spacer = QtWidgets.QWidget(self)
        right_spacer.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

        # fill the bottom toolbar
        self.toolBar_Bottom.addWidget(left_spacer)
        self.toolBar_Bottom.addActions((rewind_action, play_action, stop_action, fastforward_action))
        self.toolBar_Bottom.addWidget(right_spacer)
        self.toolBar_Bottom.setIconSize(QtCore.QSize(35, 35))
        # for action in self.toolBar_Bottom.actions():
        #     widget = self.toolBar_Bottom.widgetForAction(action)
        #     widget.setFixedSize(35, 35)

        self.toolBar_Bottom.setMinimumSize(self.toolBar_Bottom.sizeHint())
        self.toolBar_Bottom.setStyleSheet('QToolBar{spacing:8px;}')

        # Create the layout

        # The main window has 6 components in the following order:
        # Menu Bar - Tool Bar - Image viewer - Tool Bar - Slider - Status Bar

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.menuBar)
        layout.addWidget(self.toolBar_Top)
        layout.addWidget(self.displayImage)
        layout.addWidget(self.toolBar_Bottom)
        layout.addWidget(self.slider_Bottom)
        self.setStatusBar(self.statusBar_Bottom)

        # Set the defined layout in the main window
        self.main_Widget.setLayout(layout)
        
        self.setGeometry(300, 100, 600, 800)

    def openvideofile(self):
        # load a file using the widget
        name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Video File',
            '', "Video files (*.mp4 *.avi *.mov *.MP4 *.AVI *.MOV)")

        if not name:
            pass
        else:

            name = os.path.normpath(name)
            # Remove previous video handlers to avoid taking odd frames
            self.video_handler = None
            # change window name to match the file name
            self.setWindowTitle('Video Processing - ' + name.split(os.path.sep)[-1])

            # user provided a video, open it using OpenCV
            self.video_handler = VideoInformation(name)  # read the video
            success, image = self.video_handler.read()  # get the first frame

            # video was read sucessfully, update this information in the class taking care of the slider
            self.class_slider.video_handler = self.video_handler.video_handler
            self.class_slider.image_viewer = self.displayImage
            
            if success:  # if the frame exists then show the image
                self.displayImage._opencvimage = image             
                self.displayImage.update_view()
                self.current_frame = 0
                # put the frame information in the app
                self.frameLabel.setText('Frame :'+str(int(self.current_frame)+1)+'/'+str(self.video_handler.video_length))
                # update the slider
                self.slider_Bottom.setMinimum(1)
                self.slider_Bottom.setMaximum(self.video_handler.video_length)
                self.slider_Bottom.blockSignals(True)
                self.slider_Bottom.setValue(1)
                self.slider_Bottom.blockSignals(False)
                self.slider_Bottom.setEnabled(True)
            # videocap.release()

    def playvideo(self):
        # verify that the video handler is not empty
        if self.video_handler is not None:
        
            self.timer.timeout.connect(self.nextframefunction)
            self.timer.start(1000.0/self.video_handler.playbackspeed)

    def nextframefunction(self):
        # verify that we are not at the last frame
        if self.current_frame < self.video_handler.video_length - 1:
            success, image = self.video_handler.read()  # get the first frame
            self.displayImage._opencvimage = image
            self.displayImage.update_view()
            self.current_frame += 1
            # put the frame information in the app
            self.frameLabel.setText(
                'Frame :' + str(int(self.current_frame) + 1) + '/' + str(self.video_handler.video_length))
            # update the slider
            self.slider_Bottom.blockSignals(True)
            self.slider_Bottom.setValue(self.current_frame + 1)
            self.slider_Bottom.blockSignals(False)

        else:
            # reached the end of the video
            self.timer.stop()

    def stopvideo(self):
        # stop video if video is playing
        if self.timer.isActive():  # verify is the video is running
            self.timer.stop()

    def slidervaluechange(self):
        """
        this functions read the slider, updates the view and then updates the slider according
        to the frame that is being displayed. Everything occurs in a new thread, so it is usually
        is slow as firing up and endings threads takes time. However, this is the best solution to
        prevent the UI from frozen, as the process of reading 'certain' frames from a cv2 video object
        is very slow and blocking
        """
        if self.timer.isActive():  # verify is the video is running
            # top video playback before moving slider
            self.timer.stop()

        # read slider value from slider
        slider_value = self.slider_Bottom.value()
        # move the class that updates the viewer and slider to a new thread
        self.class_slider.moveToThread(self.thread_slider)
        # star the thread
        self.thread_slider.start()
        # update the view, pass the slider position to the function
        self.thread_slider.started.connect(lambda: self.class_slider.updateviewer(slider_value))
        # if the view was successfully updated, update the slider position
        self.class_slider.frame_number.connect(self.updateviwefromslider)
        # end the thread
        self.class_slider.finished.connect(self.thread_slider.quit)

    @pyqtSlot(int)
    def updateviwefromslider(self, frame_number):
        if frame_number is not None:
            self.current_frame = frame_number - 1
            self.frameLabel.setText(
                'Frame : ' + str(int(self.current_frame) + 1) + '/' + str(self.video_handler.video_length))
            #self.slider_Bottom.blockSignals(True)
            self.slider_Bottom.setValue(int(self.current_frame) + 1)
Пример #8
0
class Emotrics(QtWidgets.QDialog):
    def __init__(self, photograph, CalibrationType, CalibrationValue):
        super(Emotrics, self).__init__()
        #self.setGeometry(5,60,700,500)
        self.setWindowTitle(photograph._Tag)
        scriptDir = os.getcwd(
        )  #os.path.dirname(os.path.realpath(sys.argv[0]))
        self.setWindowIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'meei_3WR_icon.ico'))
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowMinMaxButtonsHint)

        self._file_name = photograph._file_name
        self._new_window = None
        self._tab1_results = None
        self._toggle_landmaks = True
        self._toggle_lines = True

        self._photograph = photograph

        self._Scale = 1  #this variable carries the scale of the image if it
        #needs to be resized, if Scale = 1 then the original
        #image was used for processing. If Scale > 1 then
        #the original image was too large and a resized image
        #was used for processing

        # create Thread  to take care of the landmarks and iris estimation
        #self.thread_landmarks = QtCore.QThread()  # no parent!

        self._CalibrationType = CalibrationType
        self._CalibrationValue = CalibrationValue

        #initialize the User Interface
        self.initUI()

    def initUI(self):
        #local directory
        scriptDir = os.getcwd()

        #image
        #read the image from file
        img_Qt = QtGui.QImage(scriptDir + os.path.sep + 'include' +
                              os.path.sep + 'icon_color' + os.path.sep +
                              'Facial-Nerve-Center.jpg')
        img_show = QtGui.QPixmap.fromImage(img_Qt)

        #the image will be displayed in the custom ImageViewer
        self.displayImage = ImageViewer()
        self.displayImage.setPhoto(img_show)

        #toolbar

        fitAction = QtWidgets.QAction('Fit image to window', self)
        fitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'fit_to_size_icon.png'))
        fitAction.triggered.connect(self.displayImage.show_entire_image)

        eyeAction = QtWidgets.QAction('Match iris diameter', self)
        eyeAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon.png'))
        eyeAction.triggered.connect(self.match_iris)

        eyeLoad = QtWidgets.QAction('Import iris position and diameter', self)
        eyeLoad.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'eye_icon_import.png'))
        eyeLoad.triggered.connect(self.load_iris)

        centerAction = QtWidgets.QAction('Find face center', self)
        centerAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'center_icon.png'))
        centerAction.triggered.connect(self.face_center)

        toggleAction = QtWidgets.QAction('Toggle landmarks', self)
        toggleAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'toggle-icon.png'))
        toggleAction.triggered.connect(self.toggle_landmarks)

        measuresAction = QtWidgets.QAction('Facial metrics', self)
        measuresAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'ruler_icon.png'))
        measuresAction.triggered.connect(self.create_new_window)

        saveAction = QtWidgets.QAction('Save results', self)
        saveAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'save_icon.png'))
        saveAction.triggered.connect(self.save_results)

        snapshotAction = QtWidgets.QAction('Save current view', self)
        snapshotAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'snapshot_icon.png'))
        snapshotAction.triggered.connect(self.save_snapshot)

        exitAction = QtWidgets.QAction('Exit', self)
        exitAction.setIcon(
            QtGui.QIcon(scriptDir + os.path.sep + 'include' + os.path.sep +
                        'icon_color' + os.path.sep + 'exit_icon.png'))
        exitAction.triggered.connect(self.close_app)

        #create the toolbar and add the actions
        self.toolBar = QtWidgets.QToolBar(self)
        self.toolBar.addActions(
            (fitAction, eyeAction, eyeLoad, centerAction, toggleAction,
             measuresAction, saveAction, snapshotAction, exitAction))

        #set the size of each icon to 50x50
        self.toolBar.setIconSize(QtCore.QSize(50, 50))

        for action in self.toolBar.actions():
            widget = self.toolBar.widgetForAction(action)
            widget.setFixedSize(50, 50)

        self.toolBar.setMinimumSize(self.toolBar.sizeHint())
        self.toolBar.setStyleSheet('QToolBar{spacing:5px;}')

        #the main window consist of the toolbar and the ImageViewer
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolBar)
        layout.addWidget(self.displayImage)
        self.setLayout(layout)

        self.load_file(self._photograph)
        self.displayImage.update_view()
        self.show()

    def create_new_window(self):
        #this creates a new window to display all the facial metrics, there

        if self.displayImage._shape is not None:
            #if the measurements window is already open then close it
            if self._new_window is not None:
                self._new_window.close()
                self._new_window = None

            #compute the facial metrics using the landmarks
            MeasurementsLeft, MeasurementsRight, MeasurementsDeviation, MeasurementsPercentual, _ = get_measurements_from_data(
                self.displayImage._shape, self.displayImage._lefteye,
                self.displayImage._righteye, self._CalibrationType,
                self._CalibrationValue)

            #send all the information the the appropiate places in the window
            self._tab1_results = CustomTabResult()

            #filling t_new_window_tab1_results he info for the right
            self._tab1_results._CE_right.setText('{0:.2f}'.format(
                MeasurementsRight.CommissureExcursion))
            self._tab1_results._SA_right.setText('{0:.2f}'.format(
                MeasurementsRight.SmileAngle))
            self._tab1_results._DS_right.setText('{0:.2f}'.format(
                MeasurementsRight.DentalShow))
            self._tab1_results._MRD1_right.setText('{0:.2f}'.format(
                MeasurementsRight.MarginalReflexDistance1))
            self._tab1_results._MRD2_right.setText('{0:.2f}'.format(
                MeasurementsRight.MarginalReflexDistance2))
            self._tab1_results._BH_right.setText('{0:.2f}'.format(
                MeasurementsRight.BrowHeight))

            #filling the info for the left
            self._tab1_results._CE_left.setText('{0:.2f}'.format(
                MeasurementsLeft.CommissureExcursion))
            self._tab1_results._SA_left.setText('{0:.2f}'.format(
                MeasurementsLeft.SmileAngle))
            self._tab1_results._DS_left.setText('{0:.2f}'.format(
                MeasurementsLeft.DentalShow))
            self._tab1_results._MRD1_left.setText('{0:.2f}'.format(
                MeasurementsLeft.MarginalReflexDistance1))
            self._tab1_results._MRD2_left.setText('{0:.2f}'.format(
                MeasurementsLeft.MarginalReflexDistance2))
            self._tab1_results._BH_left.setText('{0:.2f}'.format(
                MeasurementsLeft.BrowHeight))

            #deviation
            self._tab1_results._CE_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.CommissureExcursion))
            self._tab1_results._SA_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.SmileAngle))
            self._tab1_results._MRD1_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.MarginalReflexDistance1))
            self._tab1_results._MRD2_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.MarginalReflexDistance2))
            self._tab1_results._BH_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.BrowHeight))
            self._tab1_results._DS_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.DentalShow))
            self._tab1_results._CH_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.CommisureHeightDeviation))
            self._tab1_results._UVH_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.UpperLipHeightDeviation))
            self._tab1_results._LVH_dev.setText('{0:.2f}'.format(
                MeasurementsDeviation.LowerLipHeightDeviation))

            self._tab1_results._CE_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.CommissureExcursion))
            self._tab1_results._SA_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.SmileAngle))
            self._tab1_results._MRD1_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.MarginalReflexDistance1))
            self._tab1_results._MRD2_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.MarginalReflexDistance2))
            self._tab1_results._BH_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.BrowHeight))
            self._tab1_results._DS_dev_p.setText('{0:.2f}'.format(
                MeasurementsPercentual.DentalShow))

            delimiter = os.path.sep
            temp = self._file_name.split(delimiter)
            photo_name = temp[-1]
            photo_name = photo_name[0:-4]
            self._tab1_results._tab_name = photo_name

            #say to the window that presents the results that there is only 1 tab
            self._new_window = ShowResults(self._tab1_results)
            #show the window with the results
            self._new_window.show()

    def match_iris(self):
        #make both iris have the same diameter as the bigger one
        if self.displayImage._lefteye is not None:
            if self.displayImage._lefteye[2] < self.displayImage._righteye[2]:
                self.displayImage._lefteye[2] = self.displayImage._righteye[2]
            elif self.displayImage._lefteye[2] > self.displayImage._righteye[2]:
                self.displayImage._righteye[2] = self.displayImage._lefteye[2]
            elif self.displayImage._lefteye[2] == self.displayImage._righteye[
                    2]:
                pass

            self._toggle_lines = True
            self.displayImage._points = None
            self.displayImage.set_update_photo()

    def face_center(self):
        #find a line connecting the center of both iris and then fit a perperdicular
        #line in the middle
        if self.displayImage._shape is not None:

            if self._toggle_lines == True:
                self._toggle_lines = False
                points = estimate_lines(self.displayImage._opencvimage,
                                        self.displayImage._lefteye,
                                        self.displayImage._righteye)
                self.displayImage._points = points
                self.displayImage.set_update_photo()
            else:
                self.displayImage._points = None
                self.displayImage.set_update_photo()
                self._toggle_lines = True

    def load_file(self, photograph):

        if self._new_window is not None:
            self._new_window.close()

        self.displayImage._opencvimage = self._photograph._photo
        self.displayImage._lefteye = self._photograph._lefteye
        self.displayImage._righteye = self._photograph._righteye
        self.displayImage._shape = self._photograph._shape
        self.displayImage._boundingbox = self._photograph._boundingbox
        self.displayImage._points = self._photograph._points
        self.displayImage.update_view()

    def load_iris(self):
        #load a file using the widget
        name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Iris Position and Diameter', '',
            "Image files (*.png *.jpg *.jpeg *.tif *.tiff *.PNG *.JPG *.JPEG *.TIF *.TIFF)"
        )

        if not name:
            pass
        else:
            #if windows then transform / to \ (python stuffs)
            name = os.path.normpath(name)
            #if the measurements window is open then close it, the measures will be updated with the new eyes position
            if self._new_window is not None:
                self._new_window.close()

            #if the photo was already processed then get the information for the
            #txt file, otherwise process the photo using the landmark ans pupil
            #localization algorithms
            file_txt = name[:-4]
            file_txt = (file_txt + '.txt')
            if os.path.isfile(file_txt):
                shape, lefteye, righteye, _ = get_info_from_txt(file_txt)

                dx_left = lefteye[0] - shape[27, 0]
                dy_left = shape[27, 1] - lefteye[1]

                dx_right = shape[27, 0] - righteye[0]
                dy_right = shape[27, 1] - righteye[1]

                self.displayImage._lefteye = [
                    self.displayImage._shape[27, 0] + dx_left,
                    self.displayImage._shape[27, 1] - dy_left, lefteye[2]
                ]
                self.displayImage._righteye = [
                    self.displayImage._shape[27, 0] - dx_right,
                    self.displayImage._shape[27, 1] - dy_right, lefteye[2]
                ]
                self.displayImage.set_update_photo()

            else:
                QtWidgets.QMessageBox.warning(
                    self, "Warning",
                    "Iris information for this photograph is not avaliable",
                    QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)


#                self.displayImage._lefteye = lefteye
#                self.displayImage._righteye = righteye
#                self.displayImage.set_update_photo()

    def toggle_landmarks(self):
        #Hide - show the landmarks
        if self._toggle_landmaks is True:
            self._toggle_landmaks = False
            self.displayImage.set_update_photo(self._toggle_landmaks)
        elif self._toggle_landmaks is False:
            self._toggle_landmaks = True
            self.displayImage.set_update_photo(self._toggle_landmaks)

    def save_snapshot(self):
        #save the current view
        if self.displayImage._opencvimage is not None:
            proposed_name = self._file_name[:-4] + '-landmarks'
            name, _ = QtWidgets.QFileDialog.getSaveFileName(
                self, 'Save File', proposed_name,
                'png (*.png);;jpg (*.jpg);; jpeg (*.jpeg)')

            if not name:
                pass
            else:
                #if shape then add shape to image
                temp_image = self.displayImage._opencvimage.copy()

                #draw 68 landmark points
                if self.displayImage._shape is not None:
                    temp_image = mark_picture(temp_image,
                                              self.displayImage._shape,
                                              self.displayImage._lefteye,
                                              self.displayImage._righteye,
                                              self.displayImage._points)

                cv2.imwrite(temp_image, name)

    def save_results(self):
        #save the results in a txt and xls files.
        if self._file_name is not None:
            if self.displayImage._shape is not None:
                MeasurementsLeft, MeasurementsRight, MeasurementsDeviation, MeasurementsPercentual, _ = get_measurements_from_data(
                    self.displayImage._shape, self.displayImage._lefteye,
                    self.displayImage._righteye, self._CalibrationType,
                    self._CalibrationValue)
                #
                temp = SaveWindow(self, self._file_name, self._photograph._Tag,
                                  MeasurementsLeft, MeasurementsRight,
                                  MeasurementsDeviation,
                                  MeasurementsPercentual)
                temp.exec_()

                if temp._acceptSave:

                    save_txt_file(self._file_name, self.displayImage._shape,
                                  self.displayImage._lefteye,
                                  self.displayImage._righteye,
                                  self.displayImage._boundingbox)

    def validate_exit(self):
        exit = True
        #save landmarks file if not available
        if self.displayImage._shape is not None:  # only save if there is a shape
            file_txt = self._file_name[0:-4] + '.txt'
            if not (os.path.isfile(file_txt)):
                #the file doesn'e exists, save it
                save_txt_file(self._file_name, self.displayImage._shape,
                              self.displayImage._lefteye,
                              self.displayImage._righteye,
                              self.displayImage._boundingbox)
            else:
                #the is a file available, compare with current values and save only if there are changes
                shape, lefteye, righteye, _ = get_info_from_txt(file_txt)

                if (shape == self.displayImage._shape).all() and (
                        lefteye == self.displayImage._lefteye) and (
                            righteye == self.displayImage._righteye):
                    #no change move forward
                    pass
                else:
                    buttonReply = QMessageBox.question(
                        self, 'Save changes',
                        "Landamarks positions were modified.<br>Do you want to save the changes?",
                        QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
                        QMessageBox.Cancel)
                    if buttonReply == QMessageBox.Yes:
                        save_txt_file(self._file_name,
                                      self.displayImage._shape,
                                      self.displayImage._lefteye,
                                      self.displayImage._righteye,
                                      self.displayImage._boundingbox)
                    elif buttonReply == QMessageBox.No:
                        pass
                    elif buttonReply == QMessageBox.Cancel:
                        exit = False

            return exit

    def close_app(self):

        self.close()

    def closeEvent(self, event):
        exit = self.validate_exit()
        if exit:
            #we need to close all the windows before closing the program
            if self._new_window is not None:
                self._new_window.close()
            event.accept()
            self.close()
        else:
            event.ignore()