I have been trying to read frames from webcam, using OpenCV and PyQt. I know there are a lot of examples. But I would like to use MVC (model-view-controller).
OpenCV handles controller, i created models.py for model and views.py for GUI.
I don't see any error before run the code, when i run the code GUI opens, then i press open webcam and i see this warning and error:
[ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback
Process finished with exit code 1
Here is views.py
from PyQt5.QtCore import QThread, QTimer
from PyQt5.QtWidgets import QLabel, QWidget, QPushButton, QVBoxLayout, QApplication, QHBoxLayout, QMessageBox
from models import Camera
class UI_Window(QWidget):
    def __init__(self, camera = None):
        super().__init__()
        self.camera = camera
        # Create a timer.
        self.timer = QTimer()
        self.timer.timeout.connect(Camera.nextFrameSlot)
        # Create a layout.
        layout = QVBoxLayout()
        # Add a button
        button_layout = QHBoxLayout()
        btnCamera = QPushButton("Open camera")
        btnCamera.clicked.connect(Camera.openCamera)
        button_layout.addWidget(btnCamera)
        layout.addLayout(button_layout)
        # Add a label
        self.label = QLabel()
        self.label.setFixedSize(640, 640)
        layout.addWidget(self.label)
        # Set the layout
        self.setLayout(layout)
        self.setWindowTitle("First GUI with QT")
        self.setFixedSize(800, 800)
    # https://stackoverflow.com/questions/1414781/prompt-on-exit-in-pyqt-application
class MovieThread(QThread):
    def __init__(self, camera):
        super().__init__()
        self.camera = camera
    def run(self):
        self.camera.acquire_movie(200)
if __name__ == '__main__':
    app = QApplication([])
    window = UI_Window()
    window.show()
models.py
import cv2
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtGui import QPixmap, QImage
class Camera:
    def __init__(self, camera):
        self.camera = camera
        self.cap = None
    def openCamera(self):
        self.vc = cv2.VideoCapture(0)
        # vc.set(5, 30)  #set FPS
        self.vc.set(3, 640)  # set width
        self.vc.set(4, 480)  # set height
        if not self.vc.isOpened():
            msgBox = QMessageBox()
            msgBox.setText("Failed to open camera.")
            msgBox.exec_()
            return
        self.timer.start(1000. / 24)
    # https://stackoverflow.com/questions/41103148/capture-webcam-video-using-pyqt
    def nextFrameSlot(self):
        rval, frame = self.vc.read()
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        image = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(image)
        self.label.setPixmap(pixmap)
    def initialize(self):
        self.cap = cv2.VideoCapture(self.camera)
start.py
from PyQt5.QtWidgets import QApplication
from models import Camera
from views import UI_Window
camera = Camera(0)
camera.initialize()
app = QApplication([])
start_window = UI_Window(camera)
start_window.show()
app.exit(app.exec_())