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

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

相关文章:

  • 数据分析处理库-Pandas
  • 2.1.项目管理前言
  • 除了setup的表达方法,vue3还有什么表达方法
  • MySQL 处理重复数据:保留一条与两条的实现方案
  • 鸿蒙harmonyOS:笔记 正则表达式
  • Cloudfare内网穿透配置
  • Java设计模式之中介者模式
  • YOLO11改进|全网首发|YOLO11中引入轻量级坐标注意力LCA
  • (UI自动化测试web端)第二篇:元素定位的方法_class定位
  • OpenCV平滑处理:图像去噪与模糊技术详解
  • LeetCode(704):二分查找
  • 【大模型科普】大模型:人工智能的前沿(一文读懂大模型)
  • Canal同步延迟和数据丢失优化方案
  • IBM ECM结合 第三方AI API 来实现文档分析和 RAG
  • 如何从后端实现页面跳转?
  • MLIR中Dialect的抽象层级 简介
  • 算法训练营第二十二天 | 回溯算法(四)
  • page.json和manifest.json
  • 耗时sql分析
  • 通义灵码2.0 AI 程序员体验:优化与问题解决的全过程
  • 印官员称巴基斯坦在克什米尔实控线附近开火已致7死38伤
  • 央行行长详解降准:将释放长期流动性1万亿,整体存款准备金率平均水平降至6.2%
  • 多个“网约摩托车”平台上线,工人日报:安全与监管不能掉队
  • 机器人助力、入境游、演出引流:假期纳客千万人次城市有高招
  • 十大券商看后市|A股风险偏好有回升空间,把握做多窗口
  • 公安部:“五一”假期全国社会大局稳定,治安秩序良好