QCameraViewfinder的使用

news2024/12/24 8:22:15

目录

  • 引言
  • 核心代码
  • 完整代码

引言

本文是简单使用Qt快速使用摄像头完成截图等工作,主要涉及QCamera、QCameraViewfinder、QCameraImageCapture这三个类。QCamera通过相机的信息创建,用于控制开始接收图形、停止接收图像。QCameraViewfinder则是图像的展示窗口,相当于View的作用。QCameraImageCapture用于截图操作,也是本文的主要目的。

在这里插入图片描述

核心代码

首先肯定是获取可使用的相机列表,可以通过静态函数获取,如下所示:

    // 初始化设备列表
    const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
    for(int i=0; i< availableCameras.count(); i++){
        QCameraInfo cameraInfo = availableCameras.at(i);
        m_combox->addItem(cameraInfo.description(), QVariant::fromValue(cameraInfo));
        if (cameraInfo == QCameraInfo::defaultCamera())
            m_combox->setCurrentIndex(i);
    }

然后就是通过获取的QCameraInfo去初始化QCamera,不同的相机信息都需要重写构造一个QCamera对象,建议使用智能指针,避免出现内存问题,如下所示:

void UsbCameraDialog::setCamera(const QCameraInfo &cameraInfo)
{
    m_camera.reset(new QCamera(cameraInfo));
    m_camera->setViewfinder(m_viewfinder);

	// 截图
    m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));

    connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &UsbCameraDialog::readyForCapture);
    connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &UsbCameraDialog::processCapturedImage);
    connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &UsbCameraDialog::imageSaved);
    connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
            this, &UsbCameraDialog::displayCaptureError);
}

完整代码

#include <QDialog>
#include <QScopedPointer>
#include <QCameraImageCapture>

class QPushButton;
class QComboBox;
class QCamera;
class QCameraViewfinder;
class QCameraInfo;
class UsbCameraDialog : public QDialog
{
    Q_OBJECT
public:
    explicit UsbCameraDialog(QWidget *parent = nullptr);
    ~UsbCameraDialog();

signals:
    void sig_processCapturedImage(const QImage& img);

protected:
    void showEvent(QShowEvent *event) override;
    void hideEvent(QHideEvent *event) override;

private:
    void setCamera(const QCameraInfo &cameraInfo);

private slots:
    void readyForCapture(bool ready);
    void processCapturedImage(int requestId, const QImage &img);
    void imageSaved(int id, const QString &fileName);
    void displayCaptureError(int, QCameraImageCapture::Error, const QString &errorString);

private:
    QCameraViewfinder *m_viewfinder;
    QPushButton *m_startBtn;
    QPushButton *m_stopBtn;
    QComboBox *m_combox;
    QPushButton *m_snapBtn;

    QScopedPointer<QCamera> m_camera;
    QScopedPointer<QCameraImageCapture> m_imageCapture;
};

#include <QCameraViewfinder>
#include <QCamera>
#include <QCameraInfo>
#include <QPushButton>
#include <QComboBox>
#include <QVBoxLayout>
#include <QAction>
#include <QMessageBox>
#include <QDir>
#include <QDebug>

Q_DECLARE_METATYPE(QCameraInfo)

UsbCameraDialog::UsbCameraDialog(QWidget *parent) : QDialog(parent)
{
    setFixedSize(600, 450);

    m_viewfinder = new QCameraViewfinder(this);

    m_startBtn = new QPushButton("start", this);
    connect(m_startBtn, &QPushButton::clicked, this, [this] {
        m_camera->start();
    });

    m_stopBtn = new QPushButton("stop", this);
    connect(m_stopBtn, &QPushButton::clicked, this, [this] {
        m_camera->stop();
    });

    m_combox = new QComboBox(this);
    connect(m_combox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](){
        setCamera(m_combox->currentData().value<QCameraInfo>());
    });
    // 初始化设备列表
    const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
    for(int i=0; i< availableCameras.count(); i++){
        QCameraInfo cameraInfo = availableCameras.at(i);
        m_combox->addItem(cameraInfo.description(), QVariant::fromValue(cameraInfo));
        if (cameraInfo == QCameraInfo::defaultCamera())
            m_combox->setCurrentIndex(i);
    }

    m_snapBtn = new QPushButton("snap", this);
    connect(m_snapBtn, &QPushButton::clicked, this, [this] {
        m_imageCapture->capture("capture.jpg");
    });

    // 布局
    auto buttonLayout = new QHBoxLayout;
    buttonLayout->addWidget(m_combox);
    buttonLayout->addWidget(m_startBtn);
    buttonLayout->addWidget(m_stopBtn);

    auto mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(m_viewfinder);
    mainLayout->addLayout(buttonLayout);
    mainLayout->addWidget(m_snapBtn);
}

UsbCameraDialog::~UsbCameraDialog()
{

}

void UsbCameraDialog::showEvent(QShowEvent *)
{
    if(m_combox->count()){
        setCamera(m_combox->currentData().value<QCameraInfo>());
        m_camera->start();
    }
}

void UsbCameraDialog::hideEvent(QHideEvent *)
{
    if(m_camera){
        m_camera->stop();
    }
}

void UsbCameraDialog::setCamera(const QCameraInfo &cameraInfo)
{
    m_camera.reset(new QCamera(cameraInfo));
    m_camera->setViewfinder(m_viewfinder);

    m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));

    connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &UsbCameraDialog::readyForCapture);
    connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &UsbCameraDialog::processCapturedImage);
    connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &UsbCameraDialog::imageSaved);
    connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
            this, &UsbCameraDialog::displayCaptureError);
}

void UsbCameraDialog::readyForCapture(bool ready)
{
    m_snapBtn->setEnabled(ready);
}

void UsbCameraDialog::processCapturedImage(int requestId, const QImage &img)
{
    Q_UNUSED(requestId);
    emit sig_processCapturedImage(img);
    close();
}

void UsbCameraDialog::imageSaved(int id, const QString &fileName)
{
    Q_UNUSED(id);
    qDebug() << fileName;
}

void UsbCameraDialog::displayCaptureError(int id, QCameraImageCapture::Error error, const QString &errorString)
{
    Q_UNUSED(id);
    Q_UNUSED(error);
    QMessageBox::warning(this, QString("Image Capture Error"), errorString);
}
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    auto label = new QLabel("This is label", this);
    label->setFixedSize(150, 200);
    label->setStyleSheet("QLabel {border: 1px solid black;}");

    m_cameraDlg = new UsbCameraDialog(this);
    connect(m_cameraDlg, &UsbCameraDialog::sig_processCapturedImage, this, [=](const QImage &img) {
        QImage scaledImage = img.scaled(label->size(),
                                        Qt::KeepAspectRatio,
                                        Qt::SmoothTransformation);

        label->setPixmap(QPixmap::fromImage(scaledImage));
    });

    auto btn = new QPushButton("+", label);
    btn->setFixedSize(40, 40);
    btn->move(0, label->height() - btn->height());
    connect(btn, &QPushButton::clicked, this, [this] {
        m_cameraDlg->show();
    });


    auto main_widget = new QWidget(this);
    main_widget->setLayout(new QHBoxLayout);
    main_widget->layout()->addWidget(label);
    setCentralWidget(main_widget);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/630857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(1Gbit)MT28EW01GABA1LPC-0SIT、MT28EW01GABA1HPC-0SIT FLASH - NOR 存储器

MT28EW01GABA1LPC-0SIT、MT28EW01GABA1HPC-0SIT 1Gbit并行NOR闪存器件具有较高的密度、就地执行 (XiP) 性能和架构灵活性&#xff0c;可满足汽车、消费类和移动产品的设计要求。该器件非常适合用于GPS/导航、汽车后视摄像头、手机、智能手机和电子阅读器。该器件还具有较宽的温…

【小沐学Python】Python实现turtle绘画

文章目录 1、简介2、接口说明2.1 海龟动作2.1.1 移动和绘制2.1.2 获取海龟的状态 2.2 画笔控制2.2.1 绘图状态2.2.2 颜色控制2.2.3 填充2.2.4 更多绘图控制 2.3 TurtleScreen/Screen 方法2.3.1 窗口控制2.3.2 使用屏幕事件2.3.3 Screen 专有方法 3、示例测试3.1 Turtle star3.2…

关于proxy的较深入研究

关于proxy的较深入研究 proxy是什么控制台打印proxy&#xff0c;展示一下vue3中的prxoy和es6的proxy有何不同&#xff1f;proxy对js和vue3来说有什么含义&#xff1f;proxy的封装机制 proxy是什么 Proxy是ES6中新增的一个对象&#xff0c;它可以用来代理另一个对象&#xff0c…

微服务eureka和nacos

服务远程调用 /*** 创建RestTemplate并注入Spring容器* return*/Beanpublic RestTemplate restTemplate(){return new RestTemplate();} Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order orderMapper.fin…

关于调试别人的bug中发现的细节问题1:Switch...case...分支,永远只选择第一个分支

1、Switch…case…分支&#xff0c;永远只选择第一个分支&#xff1a; 原因&#xff1a;switch()里面的不是传入的变量&#xff0c;m_curWindowType是个成员变量&#xff0c;一直是初始值。他喵的&#xff0c;不知道谁写的下面的代码&#xff0c;大晚上的我也没有细看&#xff…

13.3寸_Wifi标签功耗电流计算-单面屏幕-1.8V的Flash测试

13.3寸Wifi标签不工作的时候电流的消耗主要来自两部分&#xff1a; 待机时&#xff0c;醒来监听时。经过测量&#xff0c;13.3寸Wifi标签的待机电流是7.13uA , 醒来监听的峰值电流是51.6 mA。13.3寸Wifi标签系统设定每间隔1秒醒来一次监听是否有唤醒数据。充电锂电池电池的容量…

00后跳槽到我们公司拿了25K,“躺平”两个字骗了我好久···

都说00后已经躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。前段时间我们部门就来了个00后&#xff0c;工作都还没两年&#xff0c;跳到我们公司起薪25K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。最近和他…

【配置环境】Windows下C/C++第三方库管理工具vcpkg安装和使用

一&#xff0c;vcpkg简介 vcpkg是微软公司开发的一个开源C包管理工具&#xff0c;它可以很方便的帮助您在 Windows、 Linux 和 MacOS 上下载&#xff0c;编译和安装C 第三方库。它具有自动解决依赖关系的能力&#xff0c;并且支持多种目标架构和平台。提供了超过1500个C库的预…

架构师基础篇之如何画架构图C4模型

1. 前言 本文将给大家介绍一种简洁明了软件架构可视化模型——C4模型&#xff0c;并手把手教大家如何使用代码绘制出精美的C4架构图。 阅读本文之后&#xff0c;读者画的架构图将会是这样的&#xff1a; 注&#xff1a;该图例仅作绘图示例使用&#xff0c;不确保其完整性、可…

❤ 关于以太网没有有效的ip配置问题解决方法

❤ 关于以太网没有有效的ip配置问题解决方法 错误提示 解决方法 一&#xff0c;检查IP地址是否为自动获取 1&#xff0c;首先右键任务栏右下角的网络图标点击进入"网络和共享中心",然后点击"更改适配器设置"。 2&#xff0c;在适配器界面右键"本…

异常数据检测 | Python实现孤立森林(IsolationForest)异常数据检测

文章目录 文章概述模型描述源码分享学习小结文章概述 异常数据检测 | Python实现孤立森林(IsolationForest)异常数据检测 模型描述 IsolationFores算法它是一种集成算法(类似于随机森林)主要用于挖掘异常(Anomaly)数据,或者说离群点挖掘,总之是在一大堆数据中,找出与其它数据…

***杨辉三角_yyds_LeetCode_python***

1.题目描述&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows …

第3章“程序的机器级表示”:异类的数据结构

文章目录 概述3.9.1 结构3.9.2 联合 概述 C提供了两种将不同类型的对象结合到一起来创建数据类型的机制&#xff1a;结构&#xff08;structure&#xff09;&#xff0c;用关键字 struct 来声明&#xff0c;将多个对象集合到一个单位中&#xff1b;联合&#xff08;union&…

Java网络开发(Asynchronous)—— 从 Jsp 到 Ajax 的 axios 到 vue 同步请求 到 异步请求

目录 引出如果想做bilibili边看视频边评论怎么搞&#xff1f;Ajax是啥&#xff1f;& axios的语法1. Ajax&#xff08;Asynchronous JavaScript And XML&#xff09;简介2. axios语法 及其与 java后端交互&#xff08;1&#xff09;get请求&#xff08;2&#xff09;post请求…

SpringBoot之Spring Data JPA入门学习

JPA&#xff08;Java Persistence API&#xff09;Java持久化API&#xff0c;是 Java 持久化的标准规范&#xff0c;Hibernate是持久化规范的技术实现&#xff0c;而Spring Data JPA是在 Hibernate 基础上封装的一款框架。 一、添加依赖 <dependency><groupId>or…

【git指南--命令大全】

我看好多文章命令都记录得比较发散不够全面&#xff0c;这里还是把我自己的笔记分享出来&#xff0c;方便查阅。 文章目录 1. git config作用域--list 显示当前所有配置配置cd ~/.ssh 2. 初始化 git 仓库1、把已有项目代码纳入 git 管理2、新建的项目直接用git 管理3、克隆仓库…

智能指针 smart_ptr

智能指针 为什么需要智能指针&#xff1f;内存泄漏什么是内存泄漏&#xff0c;内存泄漏的危害内存泄漏分类 智能指针的使用及原理RAII智能指针的原理std::auto_ptrstd::unique_ptrstd::shared_ptr 为什么需要智能指针&#xff1f; 下面我们先分析一下下面这段程序有没有什么内…

ps打开出现dll文件丢失怎么办,dll修复的三个方法

在Windows中&#xff0c;动态链接库&#xff08;DLL&#xff09;是一种可重用的代码和数据结构&#xff0c;它由多个应用程序共享&#xff0c;以提高内存利用率并减少冗余。DLL文件通常包含操作系统函数、图形驱动程序、网络驱动程序等&#xff0c;它们在Windows启动时被加载到…

大话Stable-Diffusion-Webui-客制化主题(四)

文章目录 目标效果开始重要说明单选框以及复选框图标样式更改gradio主题构建器上传主题方式代码上传主题方式目标 在DIY的主题中更改gradio单选框组件以及复选框组件的勾选后图标样式 效果 开始 笔者在使用gradio的主题构建器的过程中发现,gradio的复选框以及单选框组件勾选…

高通 Camera HAL3:如何在CAMX中查找Android TAG

之前的博文&#xff1a;《高通 Camera HAL3&#xff1a;添加一个VendorTag》中提到过&#xff0c;MetadataTag在CamX中有两种体现&#xff0c;可以是预定义的AndroidTag或是自定义VendorTag。 自定义VendorTag博文中已经讲解了 如何在CAMX中查找AndroidTag是经常要做的事 下…