本示例,为纯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. 接口自动化有多少case?覆盖率是多少?执行完需要多久?

    case根据接口数量而定,比如两百个接口,大概有5000个用例,一个接口大概有25到30个用例,一个接口大概200ms左右响应时间 覆盖率能达到95%以上,有时候可以达到百分之百,所有接口自动化用例执 ...

  2. supervisor的使用与配置说明

    Supervisor 是用 Python 开发的一套通用的 进程管理程序 ,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启. 一. 安装 1.1 安装 # 根目录下 ...

  3. idea技巧-自定义后缀补全

    Idea技巧-Postfix Completion 在idea中可以使用.xxx进行后缀补全 比如.sout 如何自定义后缀补全? 比如.log 在idea中打开设置 File | Settings ...

  4. [学习笔记]在Linux中使用源码编译的方式安装Nginx

    ​准备工作 准备nginx源码包: http://nginx.org/en/download.html 准备相关的依赖包以及环境: gzip 模块需要 zlib 库  http://www.zlib. ...

  5. 使用Mockito与Squaretest进行单元测试.

    项目开发过程中,不少公司都要求写单元测试的代码,可以提高代码的质量,并且可以减少出现BUG的概率. 对于中小型公司来说,对单元测试不做硬性要求,不写最好.因为还是需要一定的工作量,在保证代码质量和性能 ...

  6. audio currentTime 设置后,重置成0,解决方案(流文件-下载文件)

    audio currentTime 设置后,重置成0,解决方案 第一步-流文件-下载文件: 先查看你的mp3文件是 流文件,还是下载文件. 检测方式,就是放到浏览器回车.在线播放就是流文件,直接下载了 ...

  7. SpringSecurity(7)--- Security+JWT搭建简单的授权服务器和资源服务器

    Security+JWT搭建简单的授权服务器和资源服务器 之前有两篇博客分别将来介绍了 OAuth 2.0 和 JWT 1.OAuth 2.0详解 2.SpringSceurity(6)---JWT详 ...

  8. Android网络收集和ping封装库

    目录介绍 01.基础介绍 02.stetho大概流程 03.Android中应用 04.如何使用 05.案例截图如下 06.网络请求接口信息 07.如何使用ping 01.基础介绍 该工具作用 诸葛书 ...

  9. ARouter路由解析

    目录介绍 01.原生跳转实现 02.实现组件跳转方式 2.1 传统跳转方式 2.2 为何需要路由 03.ARouter配置与优势 04.跨进程组件通信 4.1 URLScheme 4.2 AIDL 4 ...

  10. 记录--可视化大屏-用threejs撸一个3d中国地图

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 不想看繁琐步骤的,可以直接去github下载项目,如果可以顺便来个star哈哈 本项目使用vue-cli创建,但不影响使用,主要绘制都已封 ...