pyqt5使用cv2打开相机并在视频流中绘制一个矩形框
前言
实现
- 打开摄像头
- 将QLable的大小设置为相机支持的比例
- 使用QTimer定期刷新Label中的Pixmap
- 重载QLabel的鼠标事件方法
- 重载mousePressEvent方法,点击鼠标时记录起点坐标(此时终点坐标与起点坐标一致),并将is_drawing置为True
- 重载mouseMoveEvent方法,鼠标移动时记录终点坐标,并通过is_drawing判断是否正在移动,通过调用update更新Label内容
- 重载QLabel绘制方法paintEvent,在Label上绘制框图
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow,QWidget
from PyQt5.QtGui import QPainter, QPen, QColor
from PyQt5.QtCore import Qt, QRect
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QImage, QPixmap
import cv2
class MyLabel(QLabel):
def __init__(self, parent=None):
super(MyLabel, self).__init__(parent)
self.rect = QRect()
self.is_drawing = False
self.is_update_frame = False
self.x0 =0
self.y0 =0
self.x1 =0
self.y1 =0
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.is_drawing =True
self.x0 = event.x()
self.y0 = event.y()
self.x1 = event.x()
self.y1 = event.y()
def mouseMoveEvent(self, event) -> None:
if self.is_drawing:
self.x1 = event.x()
self.y1 = event.y()
self.update()
def paintEvent(self, event):
super().paintEvent(event)
x0 ,y0 = min(self.x0,self.x1),min(self.y0,self.y1) #左顶点坐标
x1 ,y1 =max(self.x0,self.x1),max(self.y0,self.y1) #右底部坐标
self.rect = QRect(x0, y0, abs(x1-x0), abs(y1-y0))
painter = QPainter(self)
pen = QPen(QColor(255, 0, 0)) # 蓝色
pen.setWidth(3) # 线条宽度
painter.setPen(pen)
painter.drawRect(self.rect) # 绘制矩形框
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Draw Rectangle on QLabel")
self.setGeometry(100, 100, 800, 600)
self.centralwidget = QWidget(self)
self.centralwidget.setMaximumSize(QtCore.QSize(800, 600))
self.centralwidget.setObjectName("centralwidget")
self.setCentralWidget(self.centralwidget)
self.label = MyLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.label.setCursor(Qt.CrossCursor)
self.timer = QTimer()
self.timer.timeout.connect(self.update_frame)
self.timer.start(33) # 更新频率为每秒30帧
self.cap = cv2.VideoCapture(0) # 使用默认摄像头
if not self.cap.isOpened():
print("无法打开摄像头")
sys.exit()
self.update_frame()
def update_frame(self):
self.label.is_update_frame = True
self.ret, self.frame = self.cap.read()
if not self.ret:
return
self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
h, w, ch = self.frame.shape
bytes_per_line = 3 * w
qt_image = QImage(self.frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(qt_image)
self.label.setPixmap(pixmap)
self.label.setScaledContents(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
效果
总结
。