QCameraViewfinder的使用

引言

本文是简单使用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);
}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Arui丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值