99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
import cv2
|
|
import numpy as np
|
|
from OpenGL.GL import *
|
|
from OpenGL.GLU import *
|
|
from PyQt5.QtCore import QTimer
|
|
from PyQt5.QtWidgets import QApplication, QOpenGLWidget
|
|
|
|
|
|
class VideoDisplayer(QOpenGLWidget):
|
|
def __init__(self, frame_getter=None):
|
|
super().__init__()
|
|
self.frame_getter = frame_getter # 初始化帧获取函数
|
|
self.texture = None # 纹理变量初始化为 None
|
|
self.is_update = False
|
|
|
|
def initializeGL(self):
|
|
glClearColor(0.0, 0.0, 0.0, 1.0) # 设置清除颜色为黑色
|
|
self.texture = glGenTextures(1) # 生成纹理对象
|
|
|
|
def resizeGL(self, w, h):
|
|
glViewport(0, 0, w, h) # 设置 OpenGL 视口大小
|
|
glMatrixMode(GL_PROJECTION) # 设置当前矩阵为投影矩阵
|
|
glLoadIdentity() # 重置当前矩阵为单位矩阵
|
|
gluOrtho2D(0, w, h, 0) # 设置正交投影,匹配窗口宽度和高度
|
|
glMatrixMode(GL_MODELVIEW) # 设置当前矩阵为模型视图矩阵
|
|
glLoadIdentity() # 重置当前矩阵为单位矩阵
|
|
|
|
def paintGL(self):
|
|
frame = self.frame_getter() # 获取一帧图像
|
|
if frame is None:
|
|
return
|
|
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 转换颜色通道顺序为 RGB
|
|
height, width, _ = frame.shape # 获取图像高度、宽度
|
|
|
|
# 创建 OpenGL 纹理
|
|
glBindTexture(GL_TEXTURE_2D, self.texture)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, frame.data)
|
|
|
|
# 清除颜色缓冲区和深度缓冲区
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
|
glLoadIdentity()
|
|
|
|
# 绘制纹理
|
|
glEnable(GL_TEXTURE_2D)
|
|
glBegin(GL_QUADS)
|
|
glTexCoord2f(0.0, 0.0);
|
|
glVertex2f(0, 0)
|
|
glTexCoord2f(1.0, 0.0);
|
|
glVertex2f(self.width(), 0)
|
|
glTexCoord2f(1.0, 1.0);
|
|
glVertex2f(self.width(), self.height())
|
|
glTexCoord2f(0.0, 1.0);
|
|
glVertex2f(0, self.height())
|
|
glEnd()
|
|
glDisable(GL_TEXTURE_2D)
|
|
|
|
if self.is_update:
|
|
self.update()
|
|
|
|
def set_frame_generator(self, frame_getter):
|
|
self.frame_getter = frame_getter # 设置新的帧获取函数
|
|
|
|
def start(self):
|
|
self.is_update = True
|
|
self.update()
|
|
|
|
def pause(self):
|
|
self.is_update = False
|
|
|
|
def resume(self):
|
|
self.is_update = True
|
|
self.update()
|
|
|
|
def close(self):
|
|
self.is_update = False
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cap = cv2.VideoCapture(0) # 打开默认摄像头
|
|
|
|
|
|
def get_frame():
|
|
ret, frame = cap.read() # 读取摄像头帧
|
|
if ret:
|
|
return frame
|
|
|
|
|
|
app = QApplication([]) # 创建 PyQt 应用程序对象
|
|
widget = VideoDisplayer(get_frame) # 创建 VideoDisplayer 实例,传入帧获取函数
|
|
widget.resize(640, 480) # 设置窗口初始大小
|
|
widget.show() # 显示窗口
|
|
widget.start() # 开始显示视频流
|
|
app.exec_() # 进入 PyQt 主循环
|