现在做的应用需要结合 opencv 和 PyQt5, 但是两个库之间并没有一个明确的互相读取和调用的接口.
PyQt5 读取 opencv 的原始图像数据需要经过一些转换步骤.
由于历史原因,opencv 使用的像素格式为 BGR 格式,现在的图像和视频大都是 RGB 格式,所以使用 QImage 加载 opencv 原始数据前,需要使用 cv2.cvtColor 转换数据格式到 RGB 格式,参数为 cv2.COLOR_BGR2RGB.
使用 QImage 从 opencv mat 中读取图像原始数据,这里需要指定图像矩阵的数据格式和图像的宽度和高度,上面将像素格式转换为 RGB,图像深度为 8 位,所以格式为 RGB888.
这里播放视频流是使用的 QLabel, 设置其 Pixmap 以显示图像,定义一个 QTimer, 时间间隔为 33ms, 将其 timeout 信号连接到自定义函数 play_video 上,实现视频流的播放.
大致实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import cv2 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QTimer, pyqtSlot, pyqtSignal from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtWidgets import QMainWindow, QLabel, QPushButton
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.cap = cv2.VideoCapture(0) self.timer = QTimer() self.video = QLabel() self.timer.start(33) self.timer.timeout.connect(self.play_video) @pyqtslot(name="play_video") def play_video(): ret, frame = self.cap.read() if ret: rgbframe = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) connvert_to_qt = QImage(rgbframe, rgbframe.shape[1], rgbframe[0], QImage.Format_RGB888) self.video.setPixmap(QPixmap.fromImage(connvet_to_qt))
|