Qt调用摄像头二,Pro版

发布时间 2023-03-31 16:30:15作者: 十一的杂文录

本示例,为纯Qt调用摄像头,功能会比版本一要多一点:打开摄像头,设置参数,完整拍照,框选拍照,切换分辨率,旋转,水平镜像,垂直镜像,放大,缩小

上一个版本,使用的显示窗口直接显示出摄像头画面,所以可操作性有限,

没关系,这个版本使用的另一种方法:打开设备,获取视频帧,自己把视频帧画上去,这样就操作的东西就多了。

 

涉及到的功能有:

  获取摄像头列表

  获取摄像头分辨率

  获取摄像头帧率

  获取摄像头支持的视频模式

  设置摄像头参数

  完整拍照,框选拍照(使用鼠标左键画出框选的区域)

  旋转(代码中只写向统一方向旋转)

  镜像(水平镜像,垂直镜像)

  缩放(放大,缩小)

 

本demo还存在两个小bug
1.旋转后,图像不居中。修复方法:paintEvent 中加入判断,开启旋转后,图像设置居中,空白区域白色填充
2.框选后,无法取消框选。修复方法:mouseReleaseEvent 中加入判断,要是鼠标抬起的坐标和按下的坐标一致,就不框选。或者设置鼠标右键取消框选

 

QT       += core gui multimedia multimediawidgets printsupport

 

 

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QCamera>                  // 摄像头
#include <QCameraInfo>              // 摄像头信息
#include <QVideoProbe>              // 视频
#include <QVideoWidget>             // 视频显示窗口
#include <QCameraImageCapture>      // 拍照
#include <QDebug>

#include <QPaintEvent>
#include <QPainter>
#include <QMouseEvent>


QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

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

    //CameraDevice *m_pCameraDevice;

    void paintEvent(QPaintEvent *e);
    void mousePressEvent(QMouseEvent* e);
    void mouseReleaseEvent(QMouseEvent* e);


public slots:
    void slotOnProbeFrame(const QVideoFrame &frame);

private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();
    void on_pushButton_5_clicked();
    void on_pushButton_6_clicked();
    void on_pushButton_7_clicked();

private:
    Ui::Dialog *ui;

    // 需要用到的一些参数
    QImage m_img;                  // 视频帧,全局图像
    int m_rotate = 0;              // 旋转角度
    bool m_horizontal = false;     // 水平镜像
    bool m_vertical = false;       // 垂直镜像
    double m_scaled = 1.0;         // 缩放
    bool m_kuangxuan_state = false;// 框选状态
    QRect m_kuangxuan;             // 框选矩形位置

    QCamera *dev = nullptr;        // 摄像头
    QVideoProbe *video = nullptr;  // 视频
    QList<QSize> resolution;       // 分辨率
};
#endif // DIALOG_H

 

 

 

 

#include "dialog.h"
#include "ui_dialog.h"

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

    // 初始化,读取摄像头信息
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
    foreach(const QCameraInfo &cameraInfo, cameras)
    {
        qDebug() << cameraInfo.deviceName();    // 摄像头完整信息
        qDebug() << cameraInfo.description();   // 摄像头名称
    }


    dev = new QCamera(cameras.at(0));           // 创建设备
    video = new QVideoProbe;                    // 创建视频
    if(video != nullptr)
    {
        video->setSource(dev);
        connect(video, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(slotOnProbeFrame(QVideoFrame)), Qt::QueuedConnection);
    }
    dev->setCaptureMode(QCamera::CaptureViewfinder);    // 设置捕捉模式为视频,CaptureViewfinder,CaptureVideo,CaptureStillImage
    dev->load();                                        // 加载摄像头


    // 获取分辨率列表
    QList<QSize> resolution_old = dev->supportedViewfinderResolutions();
    resolution = {};
    while(!resolution_old.isEmpty())
    {
        resolution.append(resolution_old.takeLast());
    }
    qDebug() << resolution.length();
    for (int i=0; i< resolution.length(); i++) {
        qDebug() << resolution.at(i).width() << "_" << resolution.at(i).height();
    }

    // 获取摄像头帧率
    QList<QCamera::FrameRateRange> frameRate = dev->supportedViewfinderFrameRateRanges();
    foreach (auto i, frameRate)
    {
        qDebug() << i.maximumFrameRate;
    }

    // 获取摄像头支持视频格式
    QList<QVideoFrame::PixelFormat> pixelFormat = dev->supportedViewfinderPixelFormats();
    foreach (auto i, pixelFormat)
    {
        qDebug() << i;
    }

    // 设置分辨率 & 帧率 (不能同时设置最大帧率和最小帧率,会报错)
    QCameraViewfinderSettings set;
    set.setResolution(resolution.at(0));
    set.setMinimumFrameRate(15.0);
    set.setPixelFormat(QVideoFrame::Format_Jpeg);
    dev->setViewfinderSettings(set);
    dev->start();
}

Dialog::~Dialog()
{
    delete ui;
}


void Dialog::slotOnProbeFrame(const QVideoFrame &frame)
{
    //qDebug() << "获取到视频帧";

    QVideoFrame cframe(frame);
    cframe.map(QAbstractVideoBuffer::ReadOnly);

    // Windows上可以直接 QImage::fromData,但是Mac上跑不起来,所以需要做下判断
    QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(cframe.pixelFormat());
    if (imageFormat != QImage::Format_Invalid)
    {
        m_img = QImage(cframe.bits(), cframe.width(), cframe.height(), imageFormat);
    }
    else
    {
        m_img = QImage::fromData(cframe.bits(), cframe.mappedBytes());
    }
    cframe.unmap();

    // 旋转
    QMatrix matrix;
    switch (m_rotate) {
        case 1:{matrix.rotate(90);}break;
        case 2:{matrix.rotate(180);}break;
        case 3:{matrix.rotate(270);}break;
    }
    m_img = m_img.transformed(matrix);

    // 镜像
    m_img = m_img.mirrored(m_horizontal, m_vertical);

    // 缩放,数字记得写真实的分辨率
    m_img = m_img.copy(QRect(3264*(m_scaled-1)/2, 2448*(m_scaled-1)/2, 3264-3264*(m_scaled-1), 2448-2448*(m_scaled-1)));

}

void Dialog::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    p.setPen(Qt::red);
    p.drawImage(ui->widget->geometry(), m_img);
    if (m_kuangxuan_state){p.drawRect(m_kuangxuan);}
    update();
}

void Dialog::mousePressEvent(QMouseEvent* e)
{
    if (ui->widget->geometry().contains(e->pos()))
    {
        m_kuangxuan.setX(e->pos().x());
        m_kuangxuan.setY(e->pos().y());
        m_kuangxuan_state = false;
    }

}

void Dialog::mouseReleaseEvent(QMouseEvent* e)
{
    if (ui->widget->geometry().contains(e->pos()))
    {
        m_kuangxuan.setWidth(e->pos().x() - m_kuangxuan.x());
        m_kuangxuan.setHeight(e->pos().y() - m_kuangxuan.y());
        m_kuangxuan_state = true;
        qDebug() << "kuangxuan rect:" << m_kuangxuan;
    }
}

void Dialog::on_pushButton_clicked()
{
    // 拍照
    if (m_kuangxuan_state)
    {
        // 框选拍照
        QRect r2 = ui->widget->geometry();
        QRect r3;
        double b = m_img.width() / r2.width();
        double x = (m_kuangxuan.x() - r2.x()) > 0 ? (m_kuangxuan.x() - r2.x()) * b : 0;
        double y = (m_kuangxuan.y() - r2.y()) > 0 ? (m_kuangxuan.y() - r2.y()) * b : 0;
        r3.setX(x);
        r3.setY(y);
        r3.setWidth((m_kuangxuan.width() + (m_kuangxuan.x() - r2.x())) * b);
        r3.setHeight((m_kuangxuan.height() + (m_kuangxuan.y() - r2.y())) * b);
        m_img.copy(r3).save("D:\\5.jpg");

    }
    else
    {
        m_img.save("D:\\4.jpg");
    }
}

void Dialog::on_pushButton_2_clicked()
{
    // 切换分辨率
    qDebug() << resolution.at(1);

    dev->load();
    QCameraViewfinderSettings set;
    set.setResolution(resolution.at(1));
    set.setMinimumFrameRate(15.0);
    set.setPixelFormat(QVideoFrame::Format_Jpeg);
    dev->setViewfinderSettings(set);
    dev->start();
}

void Dialog::on_pushButton_3_clicked()
{
    // 旋转
    if (m_rotate < 3){m_rotate += 1;}else{m_rotate = 0;}
}

void Dialog::on_pushButton_4_clicked()
{
    // 水平镜像
    m_horizontal = m_horizontal == true ? false : true;
}

void Dialog::on_pushButton_5_clicked()
{
    // 垂直镜像
    m_vertical = m_vertical == true ? false : true;
}

void Dialog::on_pushButton_6_clicked()
{
    // 放大
    if (m_scaled < 1.9){m_scaled+=0.1;}else{m_scaled=1.9;}
    qDebug() << "scaled:" << m_scaled;
}

void Dialog::on_pushButton_7_clicked()
{
    // 缩小
    if(m_scaled>1.1){m_scaled-=0.1;}else{m_scaled=1.0;}
    qDebug() << "scaled:" << m_scaled;
}

 

 

 

嘿,成长+1