[Python] pyqt6+opencv实现摄像头图像的实时读取并显示(完整源代码)

本文介绍了如何通过OpenCV的VideoCapture类从摄像头获取实时图像,并利用PyQt6的QLabel和QTimer功能进行视频显示,同时讨论了相关布局管理和图像格式转换技巧。
摘要由CSDN通过智能技术生成

本文将会介绍如何通过opencv来实时捕获摄像头的图像,并通过pyqt6进行图像视频呈现。

实现思路

1. 通过opencv的VideoCapture类读取摄像头的每一帧图像,通过pyqt6的QLabel来显示图像

2. 根据获取的图像的宽和高大小以及QLabel的大小来动态调整最后输出的图像的宽和高

3. 调整窗体大小,动态调整显示摄像头的标签图像大小

4. 提供一个按钮来控制摄像头打开或者关闭

5. 通过QTimer实现每20毫秒刷新获取的摄像头图像,也就是产生每秒50帧的视频效果。

安装依赖

pip install opencv-python pyqt6

涉及知识点

opencv的VideoCapture(摄像头视频捕获)使用

[Python] opencv - 如何使用VideoCapture类进行摄像头视频捕获并显示

QTimer(定时器)使用

[Python] pyqt6 - Timer定时器介绍和使用场景(案例)

QGridLayout(网格布局)使用

[Python] pyqt6 - QGridLayout(网格布局)介绍和使用案例 

QImage类使用

图像格式(Format)

QImage — PyQt Documentation v6.6.0 (riverbankcomputing.com)

 rgbSwap()和rgbSwapped()方法的区别

rgbSwap()进行内部转换,直接修改QImage对象; rdbSwapped() 返回交换完之后的对象,原图像不受影响。

scaled()方法

实现对图像进行按照新的高度和宽度进行缩放,可以选择是否保持原始摄像头图像的比例。

QImage — PyQt Documentation v6.6.0 (riverbankcomputing.com)

完整源代码(带注释)

import sys

from PyQt6 import QtCore
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout, QPushButton, QWidget
from PyQt6.QtGui import QPixmap, QImage, QGuiApplication
import cv2


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('pyqt6显示opencv获取的摄像头图像')
        self.btn_camera = QPushButton('打开摄像头')  # 控制摄像头的状态
        self.lbl_img = QLabel('显示摄像头图像')  # 创建标签控件来显示摄像头的图像, 标签的大小由QGridLayout的布局来决定
        self.lbl_img.setStyleSheet('border: 1px solid black;')  # 给标签设置黑色边框
        self.lbl_img.setAlignment(Qt.AlignmentFlag.AlignCenter)  # 让标签要显示的内容居中
        self.lbl_img.setMinimumSize(640, 480)  # 宽和高保持和摄像头获取的默认大小一致
        self.btn_camera.clicked.connect(self.btn_camera_click)
        top_widget = QWidget()
        grid = QGridLayout()
        grid.addWidget(self.lbl_img, 0, 0, Qt.AlignmentFlag.AlignTop)  # 放置顶部
        grid.addWidget(self.btn_camera, 1, 0, Qt.AlignmentFlag.AlignBottom)  # 放置底部
        top_widget.setLayout(grid)
        self.setCentralWidget(top_widget)

        self.center_win()  # 居中显示主窗口

        self.is_open_camera = False  # 是否打开了摄像头标志位
        self.video_cap = None
        self.camera_timer = QtCore.QTimer(self)  # 创建读取摄像头图像的定时器
        self.camera_timer.timeout.connect(self.play_camera_video)

    def center_win(self):
        qr = self.frameGeometry()
        cp = QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def btn_camera_click(self):
        if not self.is_open_camera: # 按下 打开摄像头 按钮
            self.video_cap = cv2.VideoCapture(0)  # 打开默认摄像头(索引为0)
            print('camera fps:', self.video_cap.get(cv2.CAP_PROP_FPS))
            # 每个20毫秒获取一次摄像头的图像进行刷新, 具体设置多少合适, 可以参考你的摄像头帧率cv2.CAP_PROP_FPS,
            # 刷新频率设置一个小于 1000 / cv2.CAP_PROP_FPS 的值即可
            self.camera_timer.start(20)  
            self.is_open_camera = True
            self.btn_camera.setText('关闭摄像头')
        else:  # 按下 关闭摄像头 按钮
            self.camera_timer.stop()
            self.video_cap.release()
            self.video_cap = None
            self.lbl_img.clear()
            self.btn_camera.setText('打开摄像头')
            self.is_open_camera = False

    def play_camera_video(self):
        if self.is_open_camera:
            # ret, frame = self.video_cap.read()  # 读取视频流的每一帧
            self.video_cap.grab()
            ret, frame = self.video_cap.retrieve()  # 读取视频流的每一帧
            if ret:
                height, width, channel = frame.shape  # 获取图像高度、宽度和通道数, 通常为为640x480x3
                # opencv获取的图像默认BGR格式
                # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 转换BRG 到 RGB
                # 或者
                # 将OpenCV格式转换成QImage格式, 需要进行颜色通道交换(.rgbSwapped())
                img = QImage(frame.data, width, height, QImage.Format.Format_RGB888)
                img = img.rgbSwapped()
                # 或者
                # img = QImage(frame.data, width, height, QImage.Format.Format_RGB888)
                # img.rgbSwap()
                # 或者
                # img = QImage(frame.data, width, height, QImage.Format.Format_BGR888)
                pixmap = QPixmap.fromImage(img)  # 从QImage生成QPixmap对象
                #
                lbl_width = self.lbl_img.size().width()  # 通过size()获取图像标签的真实的宽度
                lbl_height = self.lbl_img.size().height()  # 通过size()获取图像标签的真实的高度
                # 按照图像标签的真实的宽和高进行缩放,但保持摄像头的宽和高的比例
                pixmap = QPixmap(pixmap).scaled(
                    self.lbl_img.width(), self.lbl_img.height(),
                    aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio)
                self.lbl_img.setPixmap(pixmap)  # 在标签上显示图片


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个基于 Python+PyQt+TensorFlow 的图像转素描的代码示例,供你参考: ```python import sys from PyQt5.QtCore import Qt from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QLabel, QFileDialog import tensorflow as tf import numpy as np class SketchGenerator: def __init__(self, model_path): self.model = tf.keras.models.load_model(model_path) def generate_sketch(self, image_path): # Load the input image image = tf.keras.preprocessing.image.load_img(image_path) image = tf.keras.preprocessing.image.img_to_array(image) image = np.expand_dims(image, axis=0) # Generate the sketch sketch = self.model.predict(image) # Rescale the sketch to [0, 255] sketch = (sketch * 255).astype(np.uint8) return sketch.squeeze() class MainWindow(QMainWindow): def __init__(self): super().__init__() # Create the sketch generator self.sketch_generator = SketchGenerator('sketch_generator.h5') # Create the menu bar file_menu = self.menuBar().addMenu('File') # Create the Open action open_action = QAction('Open', self) open_action.setShortcut('Ctrl+O') open_action.triggered.connect(self.open_image) file_menu.addAction(open_action) # Create the Save action save_action = QAction('Save', self) save_action.setShortcut('Ctrl+S') save_action.triggered.connect(self.save_sketch) file_menu.addAction(save_action) # Create the image label self.image_label = QLabel(self) self.image_label.setAlignment(Qt.AlignCenter) self.setCentralWidget(self.image_label) # Set the window properties self.setWindowTitle('Sketch Generator') self.setMinimumSize(640, 480) def open_image(self): # Open the file dialog file_path, _ = QFileDialog.getOpenFileName(self, 'Open Image', '', 'Images (*.png *.jpg *.jpeg *.bmp)') if file_path: # Load the image image = QImage(file_path) # Show the image self.image_label.setPixmap(QPixmap.fromImage(image)) # Generate and show the sketch sketch = self.sketch_generator.generate_sketch(file_path) sketch_image = QImage(sketch.data, sketch.shape[1], sketch.shape[0], QImage.Format_Grayscale8) self.image_label.setPixmap(QPixmap.fromImage(sketch_image)) def save_sketch(self): # Get the current pixmap pixmap = self.image_label.pixmap() if pixmap: # Open the file dialog file_path, _ = QFileDialog.getSaveFileName(self, 'Save Sketch', '', 'Images (*.png *.jpg *.jpeg *.bmp)') if file_path: # Save the pixmap pixmap.save(file_path) if __name__ == '__main__': # Create the application app = QApplication(sys.argv) # Create the main window window = MainWindow() window.show() # Run the event loop sys.exit(app.exec_()) ``` 在这个示例代码中,我们首先定义了一个 `SketchGenerator` 类,用于加载深度学习模型并生成素描风格的图像。然后,我们创建了一个 `MainWindow` 类,用于显示图像和进行用户交互。在 `MainWindow` 类中,我们创建了一个菜单栏,包含打开和保存文件的功能。当用户打开一个图像文件时,我们会在窗口中显示图像,并使用 `SketchGenerator` 类生成相应的素描风格图像。当用户保存素描风格图像时,我们会将当前的像素图保存到指定的文件中。 请注意,这个示例代码中使用的深度学习模型是一个预训练的模型,你需要使用你自己的数据集来训练一个模型。此外,你还需要安装 TensorFlow 和 PyQt5 库才能运行这个示例代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老狼IT工作室

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值