本示例,为纯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. 【Azure 应用服务】Python fastapi Function在Azure中遇见AttributeError异常(AttributeError: 'AsgiMiddleware' object has no attribute 'handle_async')

    问题描述 参考文档"Using FastAPI Framework with Azure Functions", 使用FastAPI 模块在Function中实现API请求.通过V ...

  2. 影刀rpa第一个学习项目开发所得

    1.我要在某个位置新增一条指令,但是可能没有选择好的原因,这条指令被添加到指令的最后面了,我的指令行数有几十行,然后我就要把这条指令拖动到上一屏我指定的位置上,但当我拖动指令到了当前屏最上方时,发现编 ...

  3. mysql-批量修改表的主键id,修改成联合主键

    1.sql脚本 一. 通过sql脚本,查出所有表的功能,并编写插入修改的联合主键,sql select concat('ALTER table ', TABLE_NAME, ' DROP PRIMAR ...

  4. 关于Java并发多线程的一点思考

    写在开头 在过去的2023年双11活动中,天猫的累计访问人次达到了8亿,京东超60个品牌销售破10亿,直播观看人数3.0亿人次,订单支付频率1分钟之内可达百万级峰值,这样的瞬间高并发活动,给服务端带来 ...

  5. apt-get upgrade 和apt-get dist-upgrade区别

    kali  linux系统或者 debian等系统 以及centos  在系统升级后经常会出现系统无法启动,或者启动之后GUI功能没有的问题: 笔记:   区别这两种用法 apt-get update ...

  6. 完整塔建一个spring 注解版 mybaties 过程可供复制代码

    第一步引导包.新建工程maven模块 pom.xml 中导入相对应包 ++++++++++++++++++++++++++++++++++++++++++++       1      +++++++ ...

  7. Python 初学者容易踩的坑

    哈喽大家好,我是咸鱼. 今天咸鱼列出了一些大家在初学 Python 的时候容易踩的一些坑,看看你有没有中招过. 原文:https://www.bitecode.dev/p/unexpected-pyt ...

  8. 超低延时超低功耗的2.4G无线音频收发解决方案特色解析

    为什么是我们?   团队从做芯片开始,一直在无线领域这个圈子里面混.从刚开始的wifi芯片,到后面的bt芯片,再到后面的音频算法,再到后面一起创业,做无线音频解决方案.随着和客户关系的逐渐深入,团队慢 ...

  9. buntu中查看网卡信息的基础知识

    ubuntunetworkexpress工具网络access Ubuntu 中,通常有线网卡为eth0,无线网卡则为wlan0,后续增加的以此类推(可能某些无线网卡型号命名为eth1,而非wlan0) ...

  10. C++中fopen的句柄返回NULL

    我们在使用fopen打开文件的时候有时会出现失败返回null情况,但是我们不能直接通过log具体是什么原因导致的,所以这时我们可以通过errno和strerror获取错误码和错误信息. 我遇到的是错误 ...