Python 如何使用PyQt和OpenCV读取帧
我一直在尝试使用OpenCV和PyQt从网络摄像头读取帧。我知道有很多例子。但我想使用MVC模型视图控制器 OpenCV处理控制器,我为model创建了models.py,为GUI创建了views.py 在运行代码之前,我没有看到任何错误,当我运行代码时,GUI打开,然后我按下open webcam,我看到以下警告和错误:Python 如何使用PyQt和OpenCV读取帧,python,opencv,model-view-controller,pyqt,pyqt5,Python,Opencv,Model View Controller,Pyqt,Pyqt5,我一直在尝试使用OpenCV和PyQt从网络摄像头读取帧。我知道有很多例子。但我想使用MVC模型视图控制器 OpenCV处理控制器,我为model创建了models.py,为GUI创建了views.py 在运行代码之前,我没有看到任何错误,当我运行代码时,GUI打开,然后我按下open webcam,我看到以下警告和错误: [ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674
[ 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
这里是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_())
这个代码对我有用。为了测试,我把所有的都放在一个文件中 我搬走了
camera.initialize()
我将nextFrameSlot从摄像头移动到UI_窗口
我还创建了“在UI_窗口中启动”以将self.timer.start从摄像头移动到UI_窗口
编辑:在单独的文件中测试代码
我还添加了read_gray和负片颜色readnegative=True,read_gray negative=True
顺便说一句:我在很多地方检查了frame是否为空,但如果frame不是frame,则不能使用,但如果frame不是None,则不能使用,因为frame是numpy.array,如果不是numpy.array,则可能会给出错误的结果
我从一个模型移动到另一个视图的所有GUI小部件
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)
views.py
main.py
这个代码对我有用。为了测试,我把所有的都放在一个文件中 我搬走了
camera.initialize()
我将nextFrameSlot从摄像头移动到UI_窗口
我还创建了“在UI_窗口中启动”以将self.timer.start从摄像头移动到UI_窗口
编辑:在单独的文件中测试代码
我还添加了read_gray和负片颜色readnegative=True,read_gray negative=True
顺便说一句:我在很多地方检查了frame是否为空,但如果frame不是frame,则不能使用,但如果frame不是None,则不能使用,因为frame是numpy.array,如果不是numpy.array,则可能会给出错误的结果
我从一个模型移动到另一个视图的所有GUI小部件
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)
views.py
main.py
如果您只是在寻找问题的简单答案,那么这里有一个consice替代@furas的答案: 如何使用PyQt和OpenCV读取帧 使用Python 3.7.9进行测试 requirements.txt:
numpy==1.19.4
opencv-python==4.4.0.46
PyQt5==5.15.1
PyQt5-sip==12.8.1
如果您只是在寻找问题的简单答案,那么这里有一个consice替代@furas的答案: 如何使用PyQt和OpenCV读取帧 使用Python 3.7.9进行测试 requirements.txt:
numpy==1.19.4
opencv-python==4.4.0.46
PyQt5==5.15.1
PyQt5-sip==12.8.1
您在Google中搜索过cap_msmf.cpp 674 SourceReaderCB::~SourceReaderCB终止异步回调了吗?您发现了什么?在开始时,您使用initialize,它使用cv2.videocaptureslf.camera,但也有运行camera.openCamera的按钮,它使用self.vc=cv2.VideoCapture0-因此您创建了两次访问,但没有释放第一次访问。但它不起作用,请回答您的第一条评论:这是完整的错误消息吗?难道你没有更多的错误行吗?可能还有其他有用的信息-例如,哪一行是问题所在。不幸的是,这是完整的消息您是否在Google中搜索了cap_msmf.cpp 674 SourceReaderCB::~SourceReaderCB终止异步回调?您发现了什么?在开始时,您使用initialize,它使用cv2.videocaptureslf.camera,但也有运行camera.openCamera的按钮,它使用self.vc=cv2.VideoCapture0-因此您创建了两次访问,但没有释放第一次访问。但它不起作用,请回答您的第一条评论:这是完整的错误消息吗?难道你没有更多的错误行吗?也许还有其他有用的信息-例如,哪一行是问题所在。不幸的是,这是完整的消息,它在一个文件中工作。但是当我把它分成3个文件时。我在views.py中看到错误。上面写着“未解析的摄像机引用”。nextFrameSlot和start中的摄像头未联机,您必须使用self。为了访问self.cameraI,我添加了在单独文件中测试的代码。我还添加了read_gray并将颜色转换为负片。在Camera/model中,我还将添加其他过滤器和图像修改,例如翻转、识别轮廓和其他cv2功能,这些功能在一个文件中工作。但是当我把它分成3个文件时。我在views.py中看到错误。上面写着“未解析的摄像机引用”。nextFrameSlot和start中的摄像头未联机,您必须使用self。为了访问self.cameraI,我添加了在单独文件中测试的代码。我还添加了read_gray并将颜色转换为负片。在相机/模型中,我还将添加其他过滤器和图像修改——例如翻转、识别轮廓和其他cv2功能
numpy==1.19.4
opencv-python==4.4.0.46
PyQt5==5.15.1
PyQt5-sip==12.8.1