本示例,为纯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

Qt调用摄像头二,Pro版的更多相关文章

  1. Qt调用摄像头(截取并保存图片)

    原地址:http://blog.csdn.net/liang19890820/article/details/12782531 Qt如何调用系统摄像设备进行显示.截图.录制?     QCamera: ...

  2. 使用vue做移动app时,调用摄像头扫描二维码

    现在前端技术发展飞快,前端都能做app了,那么项目中,也会遇到调用安卓手机基层的一些功能,比如调用摄像头,完成扫描二维码功能 下面我就为大家讲解一下,我在项目中调用这功能的过程. 首先我们需要一个中间 ...

  3. C# winfrom调用摄像头扫描二维码(完整版)

    前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途.发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下. 参考博客链接:https://www.cnbl ...

  4. tushare使用教程:初始化调用PRO版数据示例

    下面介绍两种常用的数据调取方式: 通过tushare python包 使用http协议直接获取 注:pro版数据接口采用语言无关的http协议实现,但也提供了多种语言的SDK数据获取. 前提条件 1. ...

  5. Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分享 ...

  6. 【视频教程】一步步将AppBox升级到Pro版

    本系列教程分为上中下三部分,通过视频的形式讲解如何将基于FineUI(开源版)的AppBox v6.0一步一步升级FineUIPro(基础版). [视频教程]一步步将AppBox升级到Pro版(上)主 ...

  7. QT 调用 DLL 方法(三种方法)

    Qt调用DLL方法一:使用Win32 API 在显式链接下,应用程序必须进行函数 调用以在运行时显式加载 DLL.为显式链接到 DLL,应用程序必须:? 调用 LoadLibrary(或相似的函 数) ...

  8. 张小龙在2017微信公开课PRO版讲了什么(附演讲实录和2016微信数据报告)

    今天2017微信公开课PRO版在广州亚运城综合体育馆举行,这次2017微信公开课大会以“下一站”为主题,而此次的微信公开课的看点大家可能就集中在腾讯公司高级副总裁.微信之父——张小龙的演讲上了!今天中 ...

  9. Android入门(十六)调用摄像头相册

    原文链接:http://www.orlion.ga/665/ 一.调用摄像头 创建一个项目ChoosePicDemo,修改activity_main.xml: <LinearLayout xml ...

  10. HTML之调用摄像头实现拍照和摄像功能

    应该有很多人知道,我们的手机里面有个功能是“抓拍入侵者”,说白了就是在解锁应用时如果我们输错了密码手机就会调用这一功能实现自动拍照. 其实在手机上还有很多我们常用的软件都有类似于这样的功能,比如微信扫 ...

随机推荐

  1. 在Study.BlazorOne项目中引入Study.Trade模块的实体的表结构

    # 1.修改EntityFrameworkCore项目下的BlazorOneDbContext文件,增加一行代码即可 增加Study.Trade.EntityFrameworkCore中的这个方法: ...

  2. 【Azure Developer】AAD API如何获取用户“Block sign in”信息(accountEnabled)

    问题描述 使用API获取所有Azure AD中的用户列表,API所参考的文档:https://docs.microsoft.com/en-us/graph/api/user-list?view=gra ...

  3. C++之指针变量的定义和使用

    从b站上黑马程序员的c++课里学到的C++之指针变量的定义和使用 指针变量的定义和使用 简单理解指针就是地址. 内存编号是从0开始记录的,一般用16进制数字表示 1 #include <iost ...

  4. Linux_Centos_yum报错总结

    ​ 此篇适用于yum报错[尝试其他镜像]并且[curl 外网]不通的情况,此时一般考虑是网络的问题 一,出现的报错信息: 此时测试curl / ping www.baidu.com会发现无法连通 二, ...

  5. 这波操作看麻了!十亿行数据,从71s到1.7s的优化之路。

    你好呀,我是歪歪. 春节期间关注到了一个关于 Java 方面的比赛,很有意思.由于是开源的,我把项目拉下来试图学(白)习(嫖)别人的做题思路,在这期间一度让我产生了一个自我怀疑: 他们写的 Java ...

  6. C++ //模板案例-数组封装类

    1 //模板案例-数组封装类 2 //描述 3 //实现一个通用的数组类 4 //1.可以对内置数据类型以及自定义数据类型的数据进行储存 5 //2.将数组很脏的数据储存到堆区 6 //3.构造函数中 ...

  7. 数据安全刻不容缓,国产智能化厂商首获SOC 2鉴证报告有何意义?

    数据安全刻不容缓,国产智能化厂商首获SOC 2鉴证报告有何意义? 了解SOC 2与ISO 27001的区别,你就知道SOC 2对智能自动化厂商的意义了 文/王吉伟 要问当前组织对于数字化转型的最大顾虑 ...

  8. Nessus 离线安装

    Nessus是渗透测试用来进行漏洞扫描的一款经常使用的工具,除此之外还是用AWVS ,APPScan后面在介绍.今天先把Ness如何离线安装到自己本机步骤说明. 安装步骤: 1.下载Nessus 官网 ...

  9. 照片也能说话了?嘴型表情全同步,AI数字人时代要来了

    SadTalker是一款先进的人工智能模型,它通过从音频中学习生成3D运动系数,并使用全新的三维面部渲染器来生成头部运动,只需传入一张照片和一段音频,就能生成高质量的AI数字人视频 工作原理 1.显式 ...

  10. MySql变量说明

    1 #变量 2 /* 3 系统变量: 4 全局变量 5 会话变量 6 7 自定义变量: 8 用户变量 9 局部变量 10 11 */ 12 #一.系统变量 13 /* 14 说明:变量由系统定义,不是 ...