当前位置: 首页 > article >正文

Qt中通过QLabel实时显示图像

      Qt中的QLabel控件用于显示文本或图像,不提供用户交互功能。以下测试代码用于从内置摄像头获取图像并实时显示:

      Widgets_Test.h:

class Widgets_Test : public QMainWindow
{
    Q_OBJECT

public:
    Widgets_Test(QWidget *parent = nullptr);
    ~Widgets_Test();

private slots:
    void start_capture();
    void close_caputre();
    void update_frame(const QImage& image);

private:
    void capture();

    Ui::Widgets_TestClass ui_;
    std::thread capture_thread_{};
    std::atomic<bool> is_running_{ false };
};

      Widgets_Test.cpp:

Widgets_Test::Widgets_Test(QWidget *parent)
    : QMainWindow(parent)
{
    ui_.setupUi(this);

    connect(ui_.button_close, &QPushButton::clicked, this, &Widgets_Test::close);
    connect(ui_.open_camera, &QPushButton::clicked, this, &Widgets_Test::start_capture);
    connect(ui_.close_camera, &QPushButton::clicked, this, & Widgets_Test::close_caputre);

    connect(ui_.open_camera, &QPushButton::clicked, this, [this] {
        ui_.button_close->setEnabled(false);
    });
    connect(ui_.close_camera, &QPushButton::clicked, this, [this] {
        ui_.button_close->setEnabled(true);
    });
}

Widgets_Test::~Widgets_Test()
{}

void Widgets_Test::start_capture()
{
    is_running_.store(true);
    capture_thread_ = std::thread([this] {
        this->capture();
    });
}

void Widgets_Test::capture()
{
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        qWarning("failed to open camera"); // QMetaObject::invokeMethod, UI操作必须在主线程中执行
        emit ui_.close_camera->clicked();
        return;
    }

    auto w1 = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
    auto h1 = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    auto w2 = ui_.label_show->width();
    auto h2 = ui_.label_show->height();
    qDebug() << w1 << "," << h1 << "," << w2 << "," << h2;

    cv::Mat frame{}, rgb{};
    QImage image{}, img_copy{};
    while (is_running_.load()) {
        cap >> frame;
        if (frame.empty())
            continue;

        cv::cvtColor(frame, rgb, cv::COLOR_BGR2RGB);
        cv::resize(rgb, rgb, cv::Size(w2, h2));
        image = QImage(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
        img_copy = image.copy();
        QMetaObject::invokeMethod(this, "update_frame", Qt::QueuedConnection, Q_ARG(QImage, img_copy));

        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void Widgets_Test::update_frame(const QImage& image)
{
    ui_.label_show->setPixmap(QPixmap::fromImage(image));
}

void Widgets_Test::close_caputre()
{
    is_running_.store(false);
    if (capture_thread_.joinable())
        capture_thread_.join();
}

      说明

      1. 在子线程中获取摄像头每帧数据:

      (1).因为QLabel中接收数据的类型为QImage,这里需要将cv::Mat转换为QImage。

      (2).通过QMetaObject::invokeMethod函数调用对象上的信号或槽函数,支持跨线程调用。这里使用此函数将子线程获取到的图像数据传给主线程上的QLabel控件。使用Qt::QueuedConnection,跨线程异步调用。

      2.UI操作必须在主线程中执行

      (1).主线程中通过QLabel的setPixmap函数显示图像。

      3.点击"open camera",开始打开摄像头采集显示图像;点击"close camera",关闭摄像头。

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Qt_Test


http://www.kler.cn/a/598330.html

相关文章:

  • 【AI大模型】搭建本地大模型GPT-NeoX:详细步骤及常见问题处理
  • AI与自媒体的深度融合路径、场景与挑战
  • opencascade 源码学习 XmlDrivers-XmlDrivers
  • 微信 MMTLS 协议详解(五):加密实现
  • Vue.js 中的 Tree Shaking:优化你的应用性能
  • 一文读懂 GPT 与 BERT:预训练逻辑及差异剖析
  • YOLO系列(v2-v5)常用命令的系统化汇总
  • 用Selenium+lxml库完成淄博链家网数据的爬取
  • 音频焦点 Android Audio Focus
  • 护网期间监测工作全解析:内容与应对策略
  • GeoTrust SSL证书有哪些种类?怎么申请?
  • 大数据从入门到入魔系列————大数据治理技术栈技术选型
  • CMake-环境变量介绍
  • Apache中间件漏洞攻略
  • 阿里qwen大模型AI智能分析实时对话生成病例的DEMO
  • 物联网(IoT)系统中,数据采集器拿来即用
  • 20届智能车赛规则已完成搜索
  • SpringBoot集成Flyway
  • iPhone 16怎么编辑图片?图片编辑技巧、软件分享
  • QT实现WPS功能