LISHUZUOXUN_yangjiang/LSZXPagesLibrary/video_displayer_opengl.py

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 主循环