本示例,为纯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. 老生常谈的iOS- weak原理,你真的懂得还是为了应付面试

    前言 weak对于iOS开发来说只要解决一些对象相互引用的时候,避免出现强强引用,对象不能被释放,出现内存泄露的问题. weak 关键字的作用域弱引用,所引用对象的计数器不会加一,并在引用对象被释放的 ...

  2. TypeScript项目开发运行(即时编译、运行,所见所得)

    1.项目*.ts自动编译 $ tsc . --watch 2.项目本地web服务运行 $ npm install --save-dev webpack-dev-server npm install - ...

  3. 【Azure Redis 缓存】应用中出现连接Redis服务错误(production.ERROR: Connection refused)的排查步骤

    问题描述 在PHP应用中,连接Redis的方法报错  RedisException(code: 0): Connection refused at /data/Redis/Connectors/Php ...

  4. 【Azure 应用服务】使用App Service for Linux/Container时,如果代码或Container启动耗时大于了230秒,默认会启动失败。

    问题描述 使用App Service for Linux/Container时,从Docker的日志中,我们可以看见有 warmup 行为,而此行为默认时间为230秒,如果超出了这个时间,就会导致Co ...

  5. 分布式事务框架seata入门

    一.简介 在近几年流行的微服务架构中,由于对服务和数据库进行了拆分,原来的一个单进程本地事务变成多个进程的本地事务,这时要保证数据的一致性,就需要用到分布式事务了.分布式事务的解决方案有很多,其中国内 ...

  6. Glide源码解析三(注册组件)

    转载请标明出处,维权必究: https://www.cnblogs.com/tangZH/p/12900387.html Glide源码解析一,初始化 Glide源码解析二-into方法 Glide源 ...

  7. 四种色彩模式ARGB_8888、ARGB_4444、 RGB_565、 ALPHA_8

    A:透明度. R:红色. G:绿色. B:蓝色. Bitmap.Config ARGB_8888:有四个8位组成,A,R,G,B各占八位,也就是各占一个字节.也就是一个像素点占4个字节,32位. Bi ...

  8. 适用mybatis和jpa的全数据库类型主键生成插件,分布式高并发有序id生成器

    适用mybatis和jpa的全数据库类型主键生成插件,分布式高并发有序id生成器

  9. 光感红外接近传感器AP3426调试总结

    一 概念 AP3426是一个高度集成了红外,光感和接近角的传感器.该传感器凭借着高灵敏度广泛应用在可穿戴领域.笔者在一个产品上用了这个传感器.花了一些时间来调试和熟悉这个传感器,这里就做一个总结吧. ...

  10. matlab在mac下无写权限解决方法和思路

    问题出在哪儿?   做音频算法很多年,使用matlab的历史也是十年多了,可是在mac下使用matlab倒是第一次,基本熟悉了之后,顺杆丝滑啊.要比在windows下好用多了,不过,中间遇到了一些问题 ...