def calculateOpticalFlowButtonClicked(self): if not self.opticalFlowLoaded: # Error: "First load optical flow images" in MessageBox msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setWindowTitle("Optical flow images are missing.") msg.setText('First load optical flow images!') msg.setStandardButtons(QMessageBox.Ok) msg.exec() return height, width = self.sequenceImages[0].shape fName = 'optical_flow.mp4' fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') video = cv2.VideoWriter(fName, fourcc, 10, (width*2, height*2)) size = 35 s = int(size/2) e = int(round(size/2)) for f in range(len(self.sequenceImages)-1): V = self.findOpticalFlowVectors(self.sequenceImages[f], self.sequenceImages[f+1], size) image = cv2.cvtColor(self.sequenceImages[f].copy(), cv2.COLOR_GRAY2RGB) image = cv2.resize(image, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC) for h in range(s, height-e, INTERVAL): for w in range(s, width-e, INTERVAL): point1 = (w*2,h*2) point2 = ((w+int(round(V[h,w,1])))*2, (h+int(round(V[h,w,0])))*2) cv2.arrowedLine(image, point1, point2, (0,255,0), 1, 8, 0, 0.25) video.write(image) video.release() videoWidget = QVideoWidget() videoWidget.setFixedSize(width*2, height*2) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.error.connect(self.handleError) self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.path.dirname(os.path.abspath(__file__)) + '/' + fName))) self.mediaPlayer.play() self.deleteItemsFromWidget(self.opticalFlowGroupBox.layout()) self.opticalFlowGroupBox.layout().addWidget(videoWidget, 0, Qt.AlignCenter)
class VideoDisplay(QWidget): def __init__(self): super().__init__() self.video_name = '' self.wholeStyleSheet = ''' QFrame{ padding-right:0.5px; padding-left:0.5px; margin-top:0.5px; margin-bottom:0.5px; height:450px; width:800px; border:4px solid rgb(0,0,205); } ''' self.sliderSheet = ''' QSlider::groove:horizontal { height: 10px; background: #63B8FF; border: 1px solid #3A5FCD; border-radius: 1px; padding-left: -1px; padding-right: -1px; } QSlider::sub-page:horizontal { height: 10px; background: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4 ); background: qlineargradient( x1:0, y1:0.2, x2:1, y2:1, stop:0 #5DCCFF, stop:1 #1874CD); border: 1px solid #4A708B; border-radius: 2px; } QSlider::add-page:horizontal { height: 10px; background: #575757; border: 0px solid #777; border-radius: 2px; } QSlider::handle:horizontal{ height:14px; width:15px; background: qlineargradient( x1:0, y1:0, x2:1, y2:1, stop:0 #104E8B, stop:1 #5CACEE); border: 1px solid #777; margin-top: -3px; margin-bottom: -3px; border-radius: 5px; } QSlider::handle:horizontal:hover{ height:14px; width:15px; background: qlineargradient( x1:1, y1:0, x2:1, y2:1, stop:0 #B0E2FF, stop:1 #FFE1FF); border: 1px solid #444; margin-top: -3px; margin-bottom: -3px; border-radius: 5px; } QSlider::sub-page:horizontal:disabled { height: 10px; background: #E0EEEE; border-color: #838B8B; } QSlider::add-page:horizontal:disabled { height: 10px; background: #C1CDCD; border-color: #838B8B; } QSlider::handle:horizontal:disabled { background: #483D8B; border: 1px solid #696969; margin-top: -3px; margin-bottom: -3px; border-radius: 4px; } ''' self.roundBtnSheet = ''' QPushButton{ border-top: 1px transparent; border-bottom: 1px transparent; border-right: 7px transparent; border-left: 7px transparent; } ''' self.initUI() def get_video_name(self): return self.video_name def initUI(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.videoWidget.setFixedSize(800, 450) self.playerFrame = QFrame() self.playerLayout = QHBoxLayout() self.playerLayout.addWidget(self.videoWidget) self.playerFrame.setLayout(self.playerLayout) self.playerFrame.setStyleSheet(self.wholeStyleSheet) self.playerWindow = QMainWindow() self.playerWindow.setCentralWidget(self.playerFrame) self.openFileBtn = QPushButton(self) self.openFileBtn.setStyleSheet(self.roundBtnSheet) self.openFileBtn.setIcon(QIcon('../icons/Folder-Open-icon.png')) self.openFileBtn.setIconSize(QSize(50, 50)) self.openFileBtn.clicked.connect(self.openFile) self.playButton = QPushButton(self) self.playButton.setStyleSheet(self.roundBtnSheet) self.playButton.setEnabled(False) self.playButton.setIcon(QIcon('../icons/Play-icon.png')) self.playButton.setIconSize(QSize(50, 50)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.setStyleSheet(self.sliderSheet) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.controlLayout = QHBoxLayout() self.controlLayout.addWidget(self.openFileBtn) self.controlLayout.addWidget(self.playButton) self.controlLayout.addWidget(self.positionSlider) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.wholeLayout = QVBoxLayout() self.wholeLayout.addWidget(self.playerWindow) self.wholeLayout.addLayout(self.controlLayout) #self.wholeLayout.addWidget(self.errorLabel) self.setLayout(self.wholeLayout) self.setStyleSheet(self.wholeStyleSheet) def openFile(self, pressed): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) self.video_name = fileName.split('/')[-1] if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() self.playButton.setIcon(QIcon('../icons/Play-icon.png')) else: self.mediaPlayer.play() self.playButton.setIcon(QIcon('../icons/Pause-icon.png')) def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
def __init__(self, parent=None, summaryImgPath=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle("Video Summarizer") self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() videoWidget.setFixedSize(880, 720) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) # Position slider self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) # Create the Image Widget self.sumImage = QImage(summaryImgPath) imgW = self.sumImage.width() imgH = self.sumImage.height() self.sumImage = self.sumImage.scaledToHeight(min(imgH, 175)) self.imageWidget = QPixmap.fromImage(self.sumImage) print(self.imageWidget.height()) self.imageLabel = QLabel() self.imageLabel.setPixmap(self.imageWidget) self.imageLabel.mousePressEvent = self.getPos self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QAction(QIcon('open.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create exit action exitAction = QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # Create menu bar and add action menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.setAlignment(Qt.AlignCenter) hLayout = QHBoxLayout() hLayout.addWidget(self.imageLabel) hLayout.setAlignment(Qt.AlignCenter) self.stackWidget = QStackedWidget(self) self.imgLabel = QLabel() self.stackImageWidget = QPixmap('') self.imgLabel.setPixmap(self.stackImageWidget) self.stackWidget.addWidget(videoWidget) self.stackWidget.addWidget(self.imgLabel) layout.addWidget(self.stackWidget) layout.addLayout(controlLayout) layout.addLayout(hLayout) layout.addWidget(self.errorLabel) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.setWindowTitle("CS576 Video Summarizer")
class VideoPlayer(QWidget): def __init__(self, parent = None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setMuted(True) #******************************************************************************* # The media player projects the media onto the videoWidget self.videoWidget = QVideoWidget() self.videoWidget.setFixedSize(450,300) #******************************************************************************* # When play is pressed, 'play' is run, and the icon changes according to # its state self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) #******************************************************************************* # This is a movable Qslider self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) #******************************************************************************* # The widgets are thrown together in a layout self.controlLayout = QHBoxLayout() self.controlLayout.setContentsMargins(0,0,0,0) self.controlLayout.addWidget(self.playButton) self.controlLayout.addWidget(self.positionSlider) self.controlLayout.setAlignment(Qt.AlignBottom) self.superLayout = QVBoxLayout() self.superLayout.addWidget(self.videoWidget) self.superLayout.addLayout(self.controlLayout) self.superLayout.addStretch(1) self.setLayout(self.superLayout) #******************************************************************************* self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) # This is where the selected video location is stored self.videoPath = None # Makes sure the videoWidget is centred frame = self.videoWidget.frameGeometry() centre = frame.center() frame.moveCenter(centre) self.move(frame.topLeft()) #******************************************************************************* def openFile(self): if self.videoPath != None: content = QMediaContent(QUrl.fromLocalFile(self.videoPath)) self.playButton.setEnabled(True) self.mediaPlayer.setMedia(content) #******************************************************************************* def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() self.videoWidget.setFixedSize(451,301) else: self.mediaPlayer.play() self.videoWidget.setFixedSize(452,301) #******************************************************************************* def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) #******************************************************************************* def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position)
class EcranConnexion(QMainWindow): """ Fenêtre de connexion au serveur de jeu. Permet à l'utilisateur de choisir un pseudo pour sa partie, de sélectionner un serveur disponible ou d'en ajouter un. Args: parent (QWidget): (OPTIONNEL) le parent auquel rattacher la fenêtre. Attributes: game (QMainWindow): la fenêtre de jeu qui s'ouvrira une fois connecté. logo (QLabel): référence au logo affiché sur l'écran btn_connect (QPushButton): bouton de connexion au serveur sélectionné dans la liste btn_local (QPushButton): bouton pour entrer manuellement les informations de connexion au serveur server_list (QListWidget): liste des serveurs enregistrés input_username (QLineEdit): pseudo du joueur, devient 'Anonyme' si la case est laissée vide """ def __init__(self, parent: QObject = None): super().__init__(parent) self.game = None uic.loadUi(os.path.join(os.getcwd(), "assets", "ecran_connexion.ui"), self) # On cherche les éléments self.logo = self.findChild(QLabel, 'logo') self.btn_connect = self.findChild(QPushButton, 'btn_connect') self.btn_add_server = self.findChild(QPushButton, 'btn_add_server') self.server_list = self.findChild(QListWidget, 'server_list') self.input_username = self.findChild(QLineEdit, 'input_username') # On connecte les boutons aux méthodes self.btn_connect.clicked.connect(self.connect_from_list) self.btn_add_server.clicked.connect(self.add_server) self.server_list.itemDoubleClicked.connect(self.connect_from_list) self.setWindowTitle( "La Bataille Brestoise - Alexandre F. & Guillaume L.") # On créer un widget vidéo et on place notre vidéo en lecture self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget(self.logo) self.logo.setFixedSize(800, int(9 / 16 * 800)) self.videoWidget.setFixedSize(800, int(9 / 16 * 800)) app_root = os.path.abspath(os.path.dirname(sys.argv[0])) movie_path = os.path.join(app_root, "assets", "background_video.mp4") self.mediaPlayer.setMedia(QMediaContent( QUrl.fromLocalFile(movie_path))) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.play() # On paramètre la liste des serveurs liste_serveurs = JsonLoader("known_servers.json")["server_list"] if len(liste_serveurs) == 0: self.add_server() else: self.refresh_server_list() def refresh_server_list(self) -> None: """ Recupère la liste des serveurs enregistrés et l'enregistre dans la liste """ self.server_list.clear() # On paramètre la liste des serveurs liste_serveurs = JsonLoader("known_servers.json")["server_list"] for server in liste_serveurs: self.server_list.addItem( QListWidgetItem( f"{server['name']} | {server['ip']} | {server['port']}")) self.server_list.setCurrentRow(0) def connect_from_list(self) -> None: """ Appelée lorsque l'utilisateur clique sur le bouton 'Connecter' Se connecter à partir d'un serveur enregistré """ nom, ip, port = self.server_list.currentItem().text().split(" | ") # On se connecte self.connect(nom, ip, port) def add_server(self) -> None: """ Appelée lorsque l'utilisateur clique sur le bouton 'Connexion locale' Ouvre la boite de dialogue correspondante """ reponse = LocalServerDialog.get_local_server_addr() # On a cliqué sur cancel if reponse is None: return else: nom, ip, port = reponse liste_serveurs = JsonLoader("known_servers.json") liste_serveurs["server_list"].append({ "name": nom, "ip": ip, "port": int(port) }) liste_serveurs.write() self.refresh_server_list() def keyPressEvent(self, event: QKeyEvent) -> None: """ Fonction héritée de Qt qui permet de prendre en charge les évènements du type touche clavier. Args: event (QKeyEvent): évènement de type touche de clavier """ if event.key() == Qt.Key_Escape: self.close() def connect(self, nom: str, ip: str, port: int) -> None: """ Appelée finalement pour se connecter au serveur et ouvrir la fenêtre de jeu. Args: nom (str): le nom affiché du serveur ip (str): l'adresse IP (IPv4) de l'hôte port (int): le port de l'hôte """ # On arrête d'abord la lecture de la video self.mediaPlayer.stop() # On récupère la boucle des évènements loop = asyncio.get_event_loop() # On en fait la boucle principale GCR.setEventLoop(loop) try: # On ouvre la connexion au serveur username = self.input_username.text() if username == "": username = GCR.getRandomName() loop.run_until_complete( TCPClientProtocol.create(nom, ip, port, username)) self.open_game() # L'astuce réside ici # On contient les évènements réseau dans un autre Thread # Comme ça le thread PyQt peut continuer de tourner GCR.tcp_thread = Thread(target=loop.run_forever) GCR.tcp_thread.start() except KeyboardInterrupt: GCR.log.log(Logger.INFORMATION, "Fin du programme client") def open_game(self) -> None: """ Ouvre la fenêtre de jeu et cache la fenêtre de connexion jusqu'à ce que la fenêtre de jeu soit fermée. """ GCR.log.log(Logger.INFORMATION, "Ouverture du jeu en cours ...") self.game = EcranJeu(self) # On connecte la fermeture de la fenêtre de jeu # A l'ouverture de la fenêtre de connexion self.game.closed.connect(self.show) self.game.show() self.hide()