【问题标题】:How to display transparent images PyQt QWidget如何显示透明图像 PyQt QWidget
【发布时间】:2021-12-06 22:25:09
【问题描述】:

我正在使用 OpenCV 进行一些图像处理,并希望使用 PyQt 小部件在我的屏幕上创建透明覆盖。下面我有一个基本示例,通过信号/插槽将基本帧从 opencv 发送到 PyQt 并将其显示在窗口上。问题是我无法使用此方法获得透明背景,而只是黑色背景:

from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout
from PyQt5.QtGui import QPixmap
import sys
import cv2
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QThread
import numpy as np
import os


class VideoThread(QThread):
    change_pixmap_signal = pyqtSignal(np.ndarray)

    def run(self):
        img = np.zeros((500, 500, 4), dtype=np.uint8)
        cv2.rectangle(img, (0, 0), (200, 200), (0, 0, 255), 2)
        while True
            self.change_pixmap_signal.emit(img)
        


class App(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Qt live label demo")
        self.disply_width = 1920
        self.display_height = 1080
        # create the label that holds the image
        self.image_label = QLabel(self)
        self.image_label.resize(self.disply_width, self.display_height)
        # create a text label
        self.textLabel = QLabel('Webcam')
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setStyleSheet("background-color:transparent;")

        # create a vertical box layout and add the two labels
        vbox = QVBoxLayout()
        vbox.addWidget(self.image_label)
        vbox.addWidget(self.textLabel)
        # set the vbox layout as the widgets layout
        self.setLayout(vbox)

        # create the video capture thread
        self.thread = VideoThread()
        # connect its signal to the update_image slot
        self.thread.change_pixmap_signal.connect(self.update_image)
        # start the thread
        self.thread.start()

    @pyqtSlot(np.ndarray)
    def update_image(self, cv_img):
        """Updates the image_label with a new opencv image"""
        qt_img = self.convert_cv_qt(cv_img)
        self.image_label.setPixmap(qt_img)

    def convert_cv_qt(self, cv_img):
        """Convert from an opencv image to QPixmap"""
        rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_image.shape
        bytes_per_line = ch * w
        convert_to_Qt_format = QtGui.QImage(
            rgb_image.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
        p = convert_to_Qt_format.scaled(
            self.disply_width, self.display_height, Qt.KeepAspectRatio)
        return QPixmap.fromImage(p)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    a = App()
    a.show()
    sys.exit(app.exec_())

如果无法将带有 alpha 通道的帧发送到 PyQt,我想知道是否可以仅发送矩形 4 点位置并使用 PyQt 绘制在屏幕上绘制矩形?我认为这需要一个 widget.update() 但我不确定在哪里调用它。

【问题讨论】:

    标签: python image opencv pyqt


    【解决方案1】:

    如果您要使用透明胶片,则颜色和图像必须是 4 通道,在您的情况下,您将 3 通道颜色传递给 cv2.rectangle 方法,然后将您使用 3 通道格式转换为图像。另一方面 cv2.rectangle 返回绘制的图像,它不修改输入数组。

    def run(self):
        img = np.zeros((500, 500, 4), dtype=np.uint8)
        output = cv2.rectangle(img, (0, 0), (200, 200), (0, 0, 255, 255), 2)
        while True:
            self.change_pixmap_signal.emit(output)
            QThread.msleep(1)
    
    def convert_cv_qt(self, cv_img):
        h, w, ch = cv_img.shape
        bytes_per_line = ch * w
        convert_to_Qt_format = QtGui.QImage(
            cv_img.data, w, h, bytes_per_line, QtGui.QImage.Format_RGBA8888
        )
        p = convert_to_Qt_format.scaled(
            self.disply_width, self.display_height, Qt.KeepAspectRatio
        )
        return QPixmap.fromImage(p)
    

    【讨论】:

    • 感谢工作。我如何将图像标签对齐到屏幕中间(垂直)。从 opencv 我发送一个 2560x720 图像并将其缩放到 1920x1080 的窗口屏幕,但随后图像出现在屏幕顶部。在 Qt 中进行视频缩放之前,我是否需要更改任何内容?我在 update_image 函数中尝试了`self.image_label.setAlignment(Qt.AlignCenter)`,但这似乎不起作用
    猜你喜欢
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多