Qt获取摄像头画面的每一帧数据
继承自QAbstractVideoSurface,实现它的一些虚函数,可以在实现的虚函数 present 中获取到摄像头画面的一帧数据,拿到数据之后就可以转换处理了,这里拿到数据之后,绘制在主窗口上了。
主要代码:
首先在 .pro 中加入 multimedia 模块:
QT += core gui multimedia multimediawidgets
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QtWidgets>
#include <QVideosurfaceFormat>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);camera_ = new QCamera;surface_ = new MyVideoSurface(this);camera_->setViewfinder(surface_);camera_->start();//这里启动
}MainWindow::~MainWindow()
{delete ui;
}QSize MainWindow::sizeHint() const
{return surface_->surfaceFormat().sizeHint();
}void MainWindow::paintEvent(QPaintEvent *event)
{QPainter painter(this);if (surface_->isActive()) {const QRect videoRect = surface_->videoRect();if (!videoRect.contains(event->rect())) {QRegion region = event->region();region = region.subtracted(videoRect);QBrush brush = palette().background();for (const QRect &rect : region){painter.fillRect(rect, brush);}}surface_->paint(&painter);//在主窗口绘制} else {painter.fillRect(event->rect(), palette().background());}
}void MainWindow::resizeEvent(QResizeEvent *event)
{QMainWindow::resizeEvent(event);surface_->updateVideoRect();
}
MyVideoSurface.h
#ifndef MYVIDEOSURFACE_H
#define MYVIDEOSURFACE_H#include <QAbstractVideoSurface>
#include <QImage>
#include <QRect>
#include <QVideoFrame>class MyVideoSurface : public QAbstractVideoSurface
{Q_OBJECTpublic:MyVideoSurface(QWidget *widget, QObject *parent = 0);QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const override;bool isFormatSupported(const QVideoSurfaceFormat &format) const override;bool start(const QVideoSurfaceFormat &format) override;bool present(const QVideoFrame &frame) override;void stop() override;QRect videoRect() const;void updateVideoRect();void paint(QPainter *painter);private:QWidget * widget_;QImage::Format imageFormat_;QRect targetRect_;QSize imageSize_;QVideoFrame currentFrame_;
};#endif
MyVideoSurface.cpp
#include "MyVideoSurface.h"#include <QtWidgets>
#include <qabstractvideosurface.h>
#include <qvideosurfaceformat.h>
#include <QVideoSurfaceFormat>MyVideoSurface::MyVideoSurface(QWidget *widget, QObject *parent): QAbstractVideoSurface(parent), widget_(widget), imageFormat_(QImage::Format_Invalid)
{}QList<QVideoFrame::PixelFormat> MyVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{if (handleType == QAbstractVideoBuffer::NoHandle) {return QList<QVideoFrame::PixelFormat>()<< QVideoFrame::Format_RGB32<< QVideoFrame::Format_ARGB32<< QVideoFrame::Format_ARGB32_Premultiplied<< QVideoFrame::Format_RGB565<< QVideoFrame::Format_RGB555;} else {return QList<QVideoFrame::PixelFormat>();}
}bool MyVideoSurface::isFormatSupported(const QVideoSurfaceFormat & format) const
{return QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()) != QImage::Format_Invalid && !format.frameSize().isEmpty() && format.handleType() == QAbstractVideoBuffer::NoHandle;
}bool MyVideoSurface::start(const QVideoSurfaceFormat &format)
{const QImage::Format imageFormat_ = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());const QSize size = format.frameSize();if (imageFormat_ != QImage::Format_Invalid && !size.isEmpty()) {this->imageFormat_ = imageFormat_;widget_->resize(size);QAbstractVideoSurface::start(format);widget_->updateGeometry();updateVideoRect();return true;}return false;
}void MyVideoSurface::stop()
{currentFrame_ = QVideoFrame();targetRect_ = QRect();QAbstractVideoSurface::stop();widget_->update();
}bool MyVideoSurface::present(const QVideoFrame &frame) //每一帧摄像头的数据,都会经过这里
{if (surfaceFormat().pixelFormat() != frame.pixelFormat() || surfaceFormat().frameSize() != frame.size()) {setError(IncorrectFormatError);stop();return false;}currentFrame_ = frame;widget_->repaint(targetRect_);return true;
}QRect MyVideoSurface::videoRect() const
{return targetRect_;
}void MyVideoSurface::updateVideoRect()
{QSize size = surfaceFormat().sizeHint();size.scale(widget_->size().boundedTo(size), Qt::KeepAspectRatio);targetRect_ = QRect(QPoint(0, 0), size);targetRect_.moveCenter(widget_->rect().center());
}void MyVideoSurface::paint(QPainter *painter)//这里绘制每一帧数据
{if (currentFrame_.map(QAbstractVideoBuffer::ReadOnly)) {//img就是转换的数据了QImage img = QImage(currentFrame_.bits(),currentFrame_.width(),currentFrame_.height(),currentFrame_.bytesPerLine(),imageFormat_).mirrored(true,false).scaled(widget_->size());painter->drawImage(targetRect_, img, QRect(QPoint(0,0),img.size()));currentFrame_.unmap();}
}
效果:
代码:https://github.com/yangyang0312/QtTestCode/tree/master/testCamera (Qt5.11)
Qt获取摄像头画面的每一帧数据相关推荐
- ios ReplayKit RPScreenRecorder获取屏幕录制的每一帧数据startCaptureWithHandler
ios ReplayKit RPScreenRecorder获取屏幕录制的每一帧数据startCaptureWithHandler 获取帧数据接口: (void)startCaptureWithHan ...
- EmguCV的配置和获取摄像头画面
如遇到"Emgu.CV.MatInvoke"的类型初始值设定项引发异常报错 ,看这里http://blog.csdn.net/qq_22033759/article/details ...
- UE4 UE5 opencv插件 获取摄像头画面
本插件在UE4.26.UE4.27.UE5.0.3等版本亲测有效,谢谢各位前辈朋友,这里就不一一鸣谢了. 插件地址:UE5OpenCV插件-C++文档类资源-CSDN下载 1.项目配置 下载后解压到工 ...
- Intel Realsense C/C++ 转 python (1)rs-hello-realsense 获取摄像头正中心对应的深度数据 get_distance()
https://dev.intelrealsense.com/docs/code-samples Demonstrates the basics of connecting to a RealSens ...
- HTML5调用本地摄像头画面,拍照,上传服务器
实现功能和适用业务 采集本地摄像头获取摄像头画面,拍照保存,上传服务器: 前端上传图片处理,展示,缩小,裁剪,上传服务器 实现步骤 调取本地摄像头(getUserMedia)/上传图片,将图片/视频显 ...
- Qt获取大华摄像头监控画面(RTSP流方式)
一.与摄像头建立连接 1.RTSP格式 //格式 rtsp://username:password@<address>:<port>/Streaming/Channels< ...
- java摄像头推流_悄摸直播(一)—— 推流器的实现(获取笔记本摄像头画面,转流推流到rtmp服务器)...
推流器 一.功能说明 获取pc端的摄像头流数据 + 展示直播效果 + 推流到rtmp服务器 二.代码实现 /** * 推流器 * @param devicePath 摄像头的地址.可以是摄像头rtsp ...
- 【UE Unreal Camera】【保姆级教程二】手把手教你通过UE获取摄像头帧数据
概述 在UE 摄像头教程一中,我们已经通过Unreal自带的媒体播放器打开了摄像头,并且将摄像头的数据展示在了游戏画面中.当然这只是最基本的功能,一般情况下,我们需要对摄像头的画面数据进行处理,比 ...
- python_获取网络(大华)摄像头画面,并存储为图片和视频
导入库 pip install opencv-python 代码 网络摄像头 ''' Opencv-python读取IP摄像头视频流 pip install opencv-python '''impo ...
最新文章
- synchronized 与 Reentrant均为可重入锁 区别后者比前者增加了长时等待可中断 设置是否公平锁 绑定多个条件
- Cetos 7 命令行登陆与图形界面登陆相互切换
- 计算机技术在工程的应用浅论,《计算机技术在计算机应用技术中的应用浅论》...
- 强制杀oracle进程
- Yii框架里用grid.CGridView调用pager扩展不显示最后一页按钮的解决
- 使用 baget 搭建 nuget 私有服务
- 01-MyBatis入门程序
- kubernetes k8s一文入门
- ldap radius mysql_OpenLDAP+FreeRADIUS+MySQL+RP-PPPOE 构建PPPOE服务器
- java debug 宏_#ifdef _DEBUG用法小结
- hdu acm 2576
- Java后端面试题总结一
- PDF编辑器中文版怎么插入PDF空白页面
- 智能道路中几个问题的探讨
- python前缀_【python刷题】前缀和
- 固态硬盘安装linux系统教程视频,固态硬盘 能安装linux系统吗
- Android桌面插件宽度,android 屏幕适配插件
- fullpage.js版本3.0.9报错问题(licenseKey)
- 如何手动开启Windows远程桌面服务
- 操作系统安全防护技术
热门文章
- Learn Convolutional Neural Network for Face Anti-Spoofing
- LWN:限制SSH agent密钥!
- Logstash 安装+配置+数据采集示例
- Vue微信公众号 创建自定义菜单
- 解决Edge浏览器使用了Infinity插件后仍被hao123绑定的问题
- UML建模之交互图——时序图、协作图
- OpenCV-图像无缝克隆函数演示(c++)
- USB充电协议CDP/SDP/DCP
- 虚幻4(ue4)下的C++(1)
- window.onload匿名函数中element.onclick正确用法