Qt调用摄像头二,Pro版
本示例,为纯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版的更多相关文章
- Qt调用摄像头(截取并保存图片)
原地址:http://blog.csdn.net/liang19890820/article/details/12782531 Qt如何调用系统摄像设备进行显示.截图.录制? QCamera: ...
- 使用vue做移动app时,调用摄像头扫描二维码
现在前端技术发展飞快,前端都能做app了,那么项目中,也会遇到调用安卓手机基层的一些功能,比如调用摄像头,完成扫描二维码功能 下面我就为大家讲解一下,我在项目中调用这功能的过程. 首先我们需要一个中间 ...
- C# winfrom调用摄像头扫描二维码(完整版)
前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途.发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下. 参考博客链接:https://www.cnbl ...
- tushare使用教程:初始化调用PRO版数据示例
下面介绍两种常用的数据调取方式: 通过tushare python包 使用http协议直接获取 注:pro版数据接口采用语言无关的http协议实现,但也提供了多种语言的SDK数据获取. 前提条件 1. ...
- Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分享 ...
- 【视频教程】一步步将AppBox升级到Pro版
本系列教程分为上中下三部分,通过视频的形式讲解如何将基于FineUI(开源版)的AppBox v6.0一步一步升级FineUIPro(基础版). [视频教程]一步步将AppBox升级到Pro版(上)主 ...
- QT 调用 DLL 方法(三种方法)
Qt调用DLL方法一:使用Win32 API 在显式链接下,应用程序必须进行函数 调用以在运行时显式加载 DLL.为显式链接到 DLL,应用程序必须:? 调用 LoadLibrary(或相似的函 数) ...
- 张小龙在2017微信公开课PRO版讲了什么(附演讲实录和2016微信数据报告)
今天2017微信公开课PRO版在广州亚运城综合体育馆举行,这次2017微信公开课大会以“下一站”为主题,而此次的微信公开课的看点大家可能就集中在腾讯公司高级副总裁.微信之父——张小龙的演讲上了!今天中 ...
- Android入门(十六)调用摄像头相册
原文链接:http://www.orlion.ga/665/ 一.调用摄像头 创建一个项目ChoosePicDemo,修改activity_main.xml: <LinearLayout xml ...
- HTML之调用摄像头实现拍照和摄像功能
应该有很多人知道,我们的手机里面有个功能是“抓拍入侵者”,说白了就是在解锁应用时如果我们输错了密码手机就会调用这一功能实现自动拍照. 其实在手机上还有很多我们常用的软件都有类似于这样的功能,比如微信扫 ...
随机推荐
- OpenCV计数应用 c++(QT)
一.前言 为了挑战一下OpenCV的学习成果,最经一直在找各类项目进行实践.机缘巧合之下,得到了以下的需求: 要求从以下图片中找出所有的近似矩形的点并计数,重叠点需要拆分单独计数. 二.解题思路 1. ...
- Cocos Creator 2.x升级至Cocos Creator 3.x
1.导入类时,批量导入 2.导入 override...关键字时,批量导入 3.this.node.scale = 0.6-->this.node.setScale(0.6, 0.6); 4.n ...
- 【Azure 存储服务】如何查看Storage Account的删除记录,有没有接口可以下载近1天删除的Blob文件信息呢?
问题描述 如何查看Storage Account的删除记录,有没有接口可以下载近1天删除的Blob文件信息呢?因为有时候出现误操作删除了某些Blob文件,想通过查看删除日志来定位被删除的文件信息. 问 ...
- 【Azure 应用服务】收集App Service 关于Availability Zone, Health check 以及 Traffic Manager的文档,并了解高可用(HA)和灾备(DR)
问题描述 收集App Service 关于Availability Zone, Health check 以及 Traffic Manager的文档,并了解高可用(HA)和灾备(DR)的具体办法 问题 ...
- 【Azure 应用服务】Python3.7项目在引用pandas 模块后,部署报错
问题描述 参考"快速入门:在 Linux 上的 Azure 应用服务中创建 Python 应用" 文档,在App Service For Linux环境中部署Python应用,在添 ...
- Nebula Graph 源码解读系列|客户端的通信秘密——fbthrift
概述 Nebula Clients 给用户提供了多种编程语言的 API 用于和 Nebula Graph 交互,并且对服务端返回的数据结构进行了重新封装,便于用户使用. 目前 Nebula Clien ...
- 以Servlet来解释 抽象实现类
在 Java Servlet API 中: Servlet 接口定义了一个 Servlet 的基本行为.这个接口是抽象的,因为它包含抽象方法,比如 service(), init(), 和 destr ...
- 英语单词组件- 单词在句子中,上面显示中文下面显示音标 css样式
原先效果: 改进demo效果 优化点 音标长度超出,或者中文超出,总宽度会按照最长的走 居中显示 再次优化 line-height: 22px; 加入这个 对齐中间行(字号大小会让绝对上下高度,对不齐 ...
- iview Button按钮 全局click事件vue拦截 节流 - 防抖 Throttle debounce
这里是按钮的节流,就没用防抖 const setVueClickGlobalThrottle = Vue => { // 节流 const on = Vue.prototype.$on Vue. ...
- 【LLM】大模型落地-从理论到实践
简述 按个人偏好和目标总结了学习目标和路径(可按需学习),后续将陆续整理出相应学习资料和资源. 学习目标 熟悉主流LLM(Llama, ChatGLM, Qwen)的技术架构和技术细节:有实际应用RA ...