通常,如果你只是想打开UVC(web camera)并显示数据的话,那最简单的方式就是使用类似下面的代码,
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr):
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
mCamera = new QCamera(this);
mCameraViewfinder = new QCameraViewfinder(this);
mCameraImageCapture = new QCameraImageCapture(mCamera, this);
mLayout = new QVBoxLayout;
mCamera->setViewfinder(mCameraViewfinder);
mLayout->addWidget(mCameraViewfinder);
mLayout->setMargin(0);
ui->scrollArea->setLayout(mLayout);
}
~Widget(){...};
private slots:
void on_captureButton_clicked(){...};
void on_stopButton_clicked(){...};
void on_playButton_clicked(){...};
private:
Ui::Widget *ui;
QCamera *mCamera;
QCameraViewfinder *mCameraViewfinder;
QCameraImageCapture *mCameraImageCapture;
QVBoxLayout *mLayout;
};
如果使用QGraphicsView和QGraphicsScene的方式,则通常用QGraphicsVideoItem会更合适,
和前面的代码类似,
QGraphicsView* gView = NULL;
QGraphicsScene* gScene = NULL;
QGraphicsVideoItem* gVideoItem = NULL;
mCamera = new QCamera(this);
gScene = new QGraphicsScene(0, 0, 800, 600);
gView = new QGraphicsView;
gView->setScene(gScene);
ui->gridLayout->addWidget(gView); //setCentralWidget(view);
gVideoItem = new GraphVideoItem;
mCamera->setViewfinder(gVideoItem);
gVideoItem->setSize(QSizeF(800, 600));
gVideoItem->setPos(0, 0);
gScene->addItem(gVideoItem);
以上的问题是,如果我们 需要把每一帧数据收集起来,例如压缩成mp4,或者通过网络发送出去,或者需要对他进行视觉图形处理(这在机器视觉中是必须的),那就必须想办法把每一帧图像转变成QImage才行。
这里我就不讲理论了,我把这个写成了一个简单易用的头文件,除了QT之外,没有任何其他依赖。如果想看完整的demo,请参考链接:
https://github.com/SpaceView/WebCamera_to_QImage_for_Qt
如果只想用到这个类,可以直接看下面的源码(源码是参考了附录【1】的源码并进行了一些修改,同时也修复了一些不同版本引发的BUG),如下,
#ifndef WEBCAME_H
#define WEBCAME_H
#include
#include
#include
#include
#include
#include
#include
#include
struct CameraInfo
{
QString identify; /* Identify of device (maybe a device path) */
QString description; /* For display */
QList resolutionList;
QStringList formatList;
};
enum FormatType {
MJPEG,
YUYV
};
struct Format {
int w;
int h;
FormatType imageFormat;
int frameRate;
};
static QImage imageFromVideoFrame(const QVideoFrame& buffer)
{
QImage img;
QVideoFrame frame(buffer); // make a copy we can call map (non-const) on
frame.map(QAbstractVideoBuffer::ReadOnly);
QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(
frame.pixelFormat());
// BUT the frame.pixelFormat() is QVideoFrame::Format_Jpeg, and this is
// mapped to QImage::Format_Invalid by
// QVideoFrame::imageFormatFromPixelFormat
if (imageFormat != QImage::Format_Invalid) {
img = QImage(frame.bits(),
frame.width(),
frame.height(),
// frame.bytesPerLine(),
imageFormat);
} else {
// e.g. JPEG
int nbytes = frame.mappedBytes();
img = QImage::fromData(frame.bits(), nbytes);
}
frame.unmap();
return img;
}
class WebCameraCapture : public QAbstractVideoSurface
{
Q_OBJECT
public:
enum PixelFormat {
Format_Invalid,
Format_ARGB32,
Format_ARGB32_Premultiplied,
Format_RGB32,
Format_RGB24,
Format_RGB565,
Format_RGB555,
Format_ARGB8565_Premultiplied,
Format_BGRA32,
Format_BGRA32_Premultiplied,
Format_BGR32,
Format_BGR24,
Format_BGR565,
Format_BGR555,
Format_BGRA5658_Premultiplied,
Format_AYUV444,
Format_AYUV444_Premultiplied,
Format_YUV444,
Format_YUV420P,
Format_YV12,
Format_UYVY,
Format_YUYV,
Format_NV12,
Format_NV21,
Format_IMC1,
Format_IMC2,
Format_IMC3,
Format_IMC4,
Format_Y8,
Format_Y16,
Format_Jpeg,
Format_CameraRaw,
Format_AdobeDng,
#ifndef Q_QDOC
NPixelFormats,
#endif
Format_User = 1000
};
Q_ENUM(PixelFormat)
explicit WebCameraCapture(QObject *parent = 0) : QAbstractVideoSurface(parent)
{
}
QList supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const override
{
Q_UNUSED(handleType);
return QList()
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?