继承自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获取摄像头画面的每一帧数据相关推荐

  1. ios ReplayKit RPScreenRecorder获取屏幕录制的每一帧数据startCaptureWithHandler

    ios ReplayKit RPScreenRecorder获取屏幕录制的每一帧数据startCaptureWithHandler 获取帧数据接口: (void)startCaptureWithHan ...

  2. EmguCV的配置和获取摄像头画面

    如遇到"Emgu.CV.MatInvoke"的类型初始值设定项引发异常报错 ,看这里http://blog.csdn.net/qq_22033759/article/details ...

  3. UE4 UE5 opencv插件 获取摄像头画面

    本插件在UE4.26.UE4.27.UE5.0.3等版本亲测有效,谢谢各位前辈朋友,这里就不一一鸣谢了. 插件地址:UE5OpenCV插件-C++文档类资源-CSDN下载 1.项目配置 下载后解压到工 ...

  4. 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 ...

  5. HTML5调用本地摄像头画面,拍照,上传服务器

    实现功能和适用业务 采集本地摄像头获取摄像头画面,拍照保存,上传服务器: 前端上传图片处理,展示,缩小,裁剪,上传服务器 实现步骤 调取本地摄像头(getUserMedia)/上传图片,将图片/视频显 ...

  6. Qt获取大华摄像头监控画面(RTSP流方式)

    一.与摄像头建立连接 1.RTSP格式 //格式 rtsp://username:password@<address>:<port>/Streaming/Channels< ...

  7. java摄像头推流_悄摸直播(一)—— 推流器的实现(获取笔记本摄像头画面,转流推流到rtmp服务器)...

    推流器 一.功能说明 获取pc端的摄像头流数据 + 展示直播效果 + 推流到rtmp服务器 二.代码实现 /** * 推流器 * @param devicePath 摄像头的地址.可以是摄像头rtsp ...

  8. 【UE Unreal Camera】【保姆级教程二】手把手教你通过UE获取摄像头帧数据

    概述   在UE 摄像头教程一中,我们已经通过Unreal自带的媒体播放器打开了摄像头,并且将摄像头的数据展示在了游戏画面中.当然这只是最基本的功能,一般情况下,我们需要对摄像头的画面数据进行处理,比 ...

  9. python_获取网络(大华)摄像头画面,并存储为图片和视频

    导入库 pip install opencv-python 代码 网络摄像头 ''' Opencv-python读取IP摄像头视频流 pip install opencv-python '''impo ...

最新文章

  1. synchronized 与 Reentrant均为可重入锁 区别后者比前者增加了长时等待可中断 设置是否公平锁 绑定多个条件
  2. Cetos 7 命令行登陆与图形界面登陆相互切换
  3. 计算机技术在工程的应用浅论,《计算机技术在计算机应用技术中的应用浅论》...
  4. 强制杀oracle进程
  5. Yii框架里用grid.CGridView调用pager扩展不显示最后一页按钮的解决
  6. 使用 baget 搭建 nuget 私有服务
  7. 01-MyBatis入门程序
  8. kubernetes k8s一文入门
  9. ldap radius mysql_OpenLDAP+FreeRADIUS+MySQL+RP-PPPOE 构建PPPOE服务器
  10. java debug 宏_#ifdef _DEBUG用法小结
  11. hdu acm 2576
  12. Java后端面试题总结一
  13. PDF编辑器中文版怎么插入PDF空白页面
  14. 智能道路中几个问题的探讨
  15. python前缀_【python刷题】前缀和
  16. 固态硬盘安装linux系统教程视频,固态硬盘 能安装linux系统吗
  17. Android桌面插件宽度,android 屏幕适配插件
  18. fullpage.js版本3.0.9报错问题(licenseKey)
  19. 如何手动开启Windows远程桌面服务
  20. 操作系统安全防护技术

热门文章

  1. Learn Convolutional Neural Network for Face Anti-Spoofing
  2. LWN:限制SSH agent密钥!
  3. Logstash 安装+配置+数据采集示例
  4. Vue微信公众号 创建自定义菜单
  5. 解决Edge浏览器使用了Infinity插件后仍被hao123绑定的问题
  6. UML建模之交互图——时序图、协作图
  7. OpenCV-图像无缝克隆函数演示(c++)
  8. USB充电协议CDP/SDP/DCP
  9. 虚幻4(ue4)下的C++(1)
  10. window.onload匿名函数中element.onclick正确用法