本示例,为纯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
标签:kuangxuan,clicked,Qt,Pro,Dialog,include,void,摄像头 From: https://www.cnblogs.com/shiyixirui/p/17276624.html