qt linux 截图,用QT5的QCamera实现USB摄像头之截图保存功能

通常来说Linux下可以通过V4L2接口及ioctl相关函数直接在底层调用摄像头设备,进行摄像头控制及图像预览和捕获,相对复杂。

QT5.0新增QMultimedia模块提供了更为方便的编程支持,模块涵盖了视,音频及摄像头功能,提供了QML类型和C++类用以处理多媒体内容。

环境: QT5.9.0  Qt Creator Ubuntu 16.04.6 LTS  Linux-4.15.0-133-generic

1.创建Qt Widgets Application工程,并添加QT +=multimedia,QT+=multimediawidgets项

2双击mainwindow.ui启动qt designer可视化布局界面

首先在布局左侧放置一个Horizental Layout控件,修改对象名为ImageView,用于图像预览显示;再在右侧放一个Vertical Layout 控件,依次在其中放置一个label和4个Push Button,修改label的对象名为ImageCapture,用于显示捕获的图像,修改按钮的显示名称及对象名分别为buttonCapture, buttonOpen,buttonSave, buttonQuit,添加一个ComboBox存放摄像头列表,拖动控件到合适的布局,如图

3. mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include

#include

#include

#include

namespace Ui {

class MainWindow;

}

class QCamera;

class QCameraViewfinder;

class QCameraImageCapture;

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

void openCamera(QString description=QString());

void enumCamera();

void bindRecoder(QCamera *camera);

private slots:

void captureImage();

void displayImage(int, QImage);

void saveImage();

void openCamera_on_clicked();

private:

Ui::MainWindow *ui;

QCamera *camera; //摄像头对象

QCameraViewfinder *viewfinder; //摄像头取景器

QCameraImageCapture *imageCapture; //截图对象

};

#endif // MAINWINDOW_

4. mainwindow.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include

#include

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

// camera=new QCamera(this);

viewfinder = new QCameraViewfinder(this);

ui->ImageView->addWidget(viewfinder);

ui->ImageCapture->setScaledContents(true);

connect(ui->buttonSave,SIGNAL(clicked()),this,SLOT(saveImage()));

connect(ui->buttonQuit,SIGNAL(clicked()),qApp,SLOT(quit()));

connect(ui->buttonOpen,SIGNAL(clicked()),this,SLOT(openCamera_on_clicked()));

enumCamera();

}

MainWindow::~MainWindow()

{

if(camera != NULL)

camera->stop();

delete ui;

}

void MainWindow::openCamera_on_clicked()

{

openCamera();

// openCamera(ui->comboBox->currentText());

}

void MainWindow::openCamera(QString description)

{

if(description.isEmpty())

{

QCameraInfo info = QCameraInfo::defaultCamera();

camera=new QCamera(info, this);

}else

{

QList cameras = QCameraInfo::availableCameras();

foreach(const QCameraInfo &cameraInfo, cameras)

{

if(cameraInfo.description() == description)

{

camera = new QCamera(cameraInfo,this);

break;

}

}

}

//camera->setCaptureMode(QCamera::CaptureVideo);

camera->setViewfinder(viewfinder);

imageCapture = new QCameraImageCapture(camera);

connect( camera, static_cast(&QCamera::error),

[=](QCamera::Error value){ qDebug()<

connect(imageCapture,SIGNAL(imageCaptured(int,QImage)),this,SLOT(displayImage(int,QImage)));

connect(ui->buttonCapture,SIGNAL(clicked()),this,SLOT(captureImage()));

camera->start();

}

void MainWindow::captureImage()

{

if(!camera)

return;

ui->statusBar->showMessage(tr("capturing..."),1000);

imageCapture->capture();

}

void MainWindow::displayImage(int id,QImage image)

{

qDebug()<"<

ui->ImageCapture->setPixmap((QPixmap::fromImage(image)));

ui->statusBar->showMessage(tr("capture OK!"),5000);

}

void MainWindow::enumCamera()

{

QList cameras = QCameraInfo::availableCameras();

foreach(const QCameraInfo &cameraInfo, cameras)

{

qDebug()<

ui->comboBox->addItem(cameraInfo.description());

}

}

void MainWindow::saveImage()

{

QString fileName=QFileDialog::getSaveFileName(this,tr("save file"),QDir::homePath(),tr("jpegfile(*.jpg)"));

if(fileName.isEmpty()){

ui->statusBar->showMessage(tr("save cancel"), 5000);

return;

}

const QPixmap* pixmap=ui->ImageCapture->pixmap();

if(pixmap){

pixmap->save(fileName);

ui->statusBar->showMessage(tr("save OK"),5000);

}

}

5.编译运行

QCamera类封装了很多底层操作,为了进一步了解Linux下的摄像头的调用机制,我们可以试验下V4L2和ioctl操作摄像头机理。

6.

#include

#include

#include

#include

#include

#include

#include

#include

int fd;

const char *input_dev = "/dev/video0";

//const char *input_dev = "/dev/vboxusb/002";

const char *qctrl_name = NULL;

int qctrl_value = 0;

struct v4l2_capability cap;

struct v4l2_queryctrl qctrl;

static void print_qctrl(struct v4l2_queryctrl *qctrl)

{

struct v4l2_control ctrl;

ctrl.id = qctrl->id;

if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0)

{

perror("get ctrl failed");

ctrl.value = -999;

}

printf("%-14s : id=%08x, type=%d, minimum=%d, maximum=%d\n"

"\t\t value = %d, step=%d, default_value=%d\n",

qctrl->name, qctrl->id, qctrl->type, qctrl->minimum, qctrl->maximum,

ctrl.value, qctrl->step, qctrl->default_value);

}

static void print_menu(struct v4l2_querymenu *menu)

{

printf("\t %d : %s\n", menu->index, menu->name);

}

static int set_qctrl(struct v4l2_queryctrl *qctrl)

{

struct v4l2_control ctrl;

printf("set %s = %d\n", qctrl_name, qctrl_value);

ctrl.id = qctrl->id;

ctrl.value = qctrl_value;

return ioctl(fd, VIDIOC_S_CTRL, &ctrl);

}

static void deal_qctrl(struct v4l2_queryctrl *qctrl)

{

print_qctrl(qctrl);

if (qctrl_name && !strcmp(qctrl_name, (const char *)qctrl->name))

set_qctrl(qctrl);

}

static void qctrl_get(int id)

{

qctrl.id = id;

if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0)

{

deal_qctrl(&qctrl);

if (qctrl.type == V4L2_CTRL_TYPE_MENU)

{

int idx;

struct v4l2_querymenu menu;

for (idx = qctrl.minimum; idx <= qctrl.maximum; idx++)

{

menu.id = qctrl.id;

menu.index = idx;

if (ioctl(fd, VIDIOC_QUERYMENU, &menu)==0)

{

print_menu(&menu);

}

}

}

}

}

int main(int argc, char **argv)

{

int ret, i;

if (argc == 3)

{

qctrl_name = argv[1];

qctrl_value = atoi(argv[2]);

}

fd = open(input_dev, O_RDWR);

if (fd < 0)

{

perror("open video failed");

return -1;

}

printf("open video '%s' success\n", input_dev);

ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);

if (ret < 0)

{

perror("ioctl querycap");

return -1;

}

if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)

{

printf("video device donot support capture\n");

return -1;

}

for (i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++)

{

qctrl_get(i);

}

for (i = V4L2_CID_PRIVATE_BASE; i < V4L2_CID_PRIVATE_BASE+25; i++)

{

qctrl_get(i);

}

printf("close video\n");

close(fd);

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以按照以下步骤实现: 1. 在.pro文件中添加multimedia模块: ``` QT += multimedia ``` 2. 在代码中引入QCamera、QCameraViewfinder和QMediaRecorder头文件: ```c++ #include <QCamera> #include <QCameraViewfinder> #include <QMediaRecorder> ``` 3. 创建一个QCamera对象和一个QCameraViewfinder对象,并将QCameraViewfinder设置为QWidget的子类: ```c++ QCamera *camera; QCameraViewfinder *viewfinder; camera = new QCamera; viewfinder = new QCameraViewfinder; viewfinder->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); viewfinder->setFixedSize(640, 480); viewfinder->setVisible(true); camera->setViewfinder(viewfinder); ``` 4. 创建一个QMediaRecorder对象并设置输出格式、输出文件名和音视频编码器: ```c++ QMediaRecorder *recorder; recorder = new QMediaRecorder(camera); // 设置输出格式 QString fileName = "video.mp4"; QMediaMetaData mediaMetaData; mediaMetaData.insert(QMediaMetaData::Title, QVariant(fileName)); recorder->setMetaData(mediaMetaData); recorder->setOutputLocation(QUrl::fromLocalFile(fileName)); // 设置音视频编码器 QVideoEncoderSettings videoSettings = recorder->videoSettings(); videoSettings.setResolution(640, 480); QAudioEncoderSettings audioSettings = recorder->audioSettings(); recorder->setVideoSettings(videoSettings); recorder->setAudioSettings(audioSettings); ``` 5. 调用QCamera的start()函数开始预览,调用QMediaRecorder的record()函数开始录制,调用QMediaRecorder的stop()函数停止录制: ```c++ // 开始预览 camera->start(); // 开始录制 recorder->record(); // 停止录制 recorder->stop(); ``` 6. 调用QCamera的searchAndLock()函数锁定摄像头并进行拍照,调用QCamera的unlock()函数解锁摄像头: ```c++ // 拍照 camera->searchAndLock(); QImage image = viewfinder->grab().toImage(); image.save("photo.jpg"); camera->unlock(); ``` 完成以上步骤后,你就可以在Qt应用程序中调用摄像头,并实现拍照和录像功能了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值