I found the program code I made a long time ago using PyQt5 and OpenCV for Python, so I will post it as a memorandum.
"""
@author : koharite
function:
Display video files.
If the correct answer frame information is specified, it will be displayed superimposed on the frame.
"""
import sys
import cv2
from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, QHBoxLayout, QLabel, QPushButton, QAction, QStyle, QFileDialog)
from PyQt5.QtGui import(QIcon, QImage, QPixmap, QPainter, QColor)
from PyQt5.QtCore import (pyqtSlot, QTimer, Qt)
#Main window configuration
class MainWindow(QMainWindow):
    #Set the initial value of the main window
    def __init__(self):
        #Window status
        super().__init__()
        self.title = 'Movie Viewer for PDET'
        self.left = 10
        self.top = 10
        self.width = 1280
        self.height = 960
        #Video status
        self.framePos = 0
        #self.image = QImage()
        self.image = None
        self.moviePlayFlg = False
        self.imgWidth = 0
        self.imgHeight = 0
        self.frameRate = 0
        self.initUI()
    #Summarize the initialization process
    def initUI(self):
        #Set the title of the main window
        self.setWindowTitle(self.title)
        #Initial position of main window
        self.setGeometry(self.left, self.top, self.width, self.height)
        hbox = QHBoxLayout(self)
        #Set the main window menu
        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu('File')
        editMenu = mainMenu.addMenu('Edit')
        optionMenu = mainMenu.addMenu('Option')
        helpMenu = mainMenu.addMenu('Help')
        #Set the menu to open the file
        fileOpenButton = QAction(self.style().standardIcon(getattr(QStyle, 'SP_FileDialogStart')), 'File Open', self)
        fileOpenButton.setShortcut('Ctrl+O')
        fileOpenButton.triggered.connect(self.openFileDialog)
        fileMenu.addAction(fileOpenButton)
        #Set the exit menu of the app
        exitButton = QAction(self.style().standardIcon(getattr(QStyle, 'SP_DialogCloseButton')), 'Exit', self)
        exitButton.setShortcut('Ctrl+Q')
        exitButton.setStatusTip('Exit application')
        exitButton.triggered.connect(self.close)
        fileMenu.addAction(exitButton)
        #Place parts in the main window
        #Set the image drawing area
        #self.showFrameLabel = QLabel(self)
        #self.painter = QPainter()
        #self.showFramePixmap = QPixmap()
        #self.painter.drawPixmap(0,0, self.imgWidth, self.imgHeight, self.showFramePixmap)
        #self.showFrameLabel.setPixmap(self.showFramePixmap)
        #self.resize(self.showFramePixmap.width(), self.showFramePixmap.height())
        #hbox.addWidget(self.showFrameLabel)
        self.setLayout(hbox)
        #Set the video play button
        moviePlayBtn = QPushButton(self.style().standardIcon(getattr(QStyle, 'SP_MediaPlay')), 'Play', self)
        moviePlayBtn.move(20, self.height-50)
        moviePlayBtn.clicked.connect(self.moviePlay)
        #Set the video stop button
        movieStopBtn = QPushButton(self.style().standardIcon(getattr(QStyle, 'SP_MediaStop')), 'Stop', self)
        movieStopBtn.move(120, self.height-50)
        movieStopBtn.clicked.connect(self.movieStop)
        #Drawing update timer
        #self.updateTimer = QTimer(self)
        #self.updateTimer.timeout.connect(self.showNextFrame)
        ##self.updateTimer.start(self)
        #Display of main window
        self.show()
    def openFileDialog(self):
        options = QFileDialog.Options()
        #options |= QFileDialog.DontUseNativeDialog
        inputFileName, _ = QFileDialog.getOpenFileName(self, 'Open File', '', 'Movie files(*.avi *.wmv)', options=options)
        #Show filename in status bar for debugging
        #self.statusBar().showMessage(inputFileName[0])
        self.statusBar().showMessage(inputFileName)
        print(inputFileName)
        #Load video with OpenCV
        self.video = cv2.VideoCapture(inputFileName)
        #debug
        print('OpenCV movie read success.')
        #Get the number of frames
        self.frameNum = self.video.get(cv2.CAP_PROP_FRAME_COUNT)
        #debug
        print('movie frameNum: ', str(self.frameNum))
        #Get frame rate
        self.frameRate = self.video.get(cv2.CAP_PROP_FPS)
        #debug
        print('movie frameRate: ', str(self.frameRate))
        #Show first frame
        self.framePos = 0
        self.video.set(cv2.CAP_PROP_POS_FRAMES, self.framePos)
        ret, frame = self.video.read()
        #debug
        print('openCV current frame read')
        #Convert playback frame from OpenCV format to PyQt QImage
        self.image = self.openCV2Qimage(frame)
        #debug
        print('convert openCV to QImage')
        self.imgWidth = self.image.width()
        self.imgHeith = self.image.height()
        #display
        #debug
        print('movie properties read success')
        #self.painter.drawPixmap(0, 0, self.imgWidth, self.imgHeight, self.image)
    def moviePlay(self):
        self.moviePlayFlg = True
        self.updateTimer.start((1/self.frameRate) * 1000)
    def movieStop(self):
        self.moviePlayFlg = False
        self.updateTimer.stop()
    def showNextFrame(self):
        if self.moviePlayFlg == False:
            return
        self.framePos += 1
        #Set the playback frame position of the video with OpenCV
        self.video.set(cv2.CAP_PROP_POS_FRAMES, self.framePos)
        ret, frame = self.video.read()
        #Convert playback frame from OpenCV format to PyQt QImage
        self.image = self.openCV2Qimage(frame)
        #self.imgWidth = self.image.width()
        #self.imgHeith  self.image.height()
    def paintEvent(self, event):
        #For debugging
        print('paintEvent Start')
        painter = QPainter()
        painter.begin(self)
        painter.setPen(QColor('#FFFFFF'))
        painter.setBrush(Qt.white)
        painter.drawRect(event.rect())
        #For debugging
        print('painter tool set')
        if self.image == None:
            return
        #image = QtGui.QImage('./sample01.jpg')
        #x = (self.width() - self.image.width()) / 2
        #y = (self.height() - self.image.height()) / 2
        #painter.drawImage(x, y, image)
        painter.drawPixmap(0, 0, self.ImgWidth, self.imgHeight, self.image)
        painter.end()
    def openCV2Qimage(self, cvImage):
        height, width, channel = cvImage.shape
        bytesPerLine = channel * width
        cvImageRGB = cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB)
        image = QImage(cvImageRGB, width, height, bytesPerLine, QImage.Format_RGB888)
        #image = QImage(cvImage, width, height, bytesPerLine, QImage.Format_RGB888)
        #image = image.rgbSwapped()
        return image
#Run the app
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())
Recommended Posts