前言
项目中需要使用USB 的免驱摄像头进行采集图像,一般这种USB的摄像头直接可以使用Qt中的QCamera获取图像及相关各种操作,这里基于QCamera来实现摄像头的显示和抓图的基本功能。
一、功能介绍和成果展示
多摄像头的信息获取、显示和抓图功能
- CameraInfo遍历设备获取多摄像头信息
- 获取摄像头的分辨率和最大帧率,并进行选择设置
- 实现单张抓图和连续抓拍功能
二、实现流程
1.配置工作
首先要在Pro文件中加入multimedia模块,如下
在ui中把图像视频显示的widget提升为QVideoWidget
2.遍历摄像头设备
调用QCameraInfo来获取可用的摄像头设备列表
cameras = QCameraInfo::availableCameras();//获取可用摄像头设备列表
int index = cameras.size();
for(int i=0;i<index;i++)
{
qDebug()<<index<<cameras.at(i).description();//摄像头的设备名称
ui->cmb_CameraName->addItem(cameras.at(i).description());
}
3.获取摄像头支持的分辨率和最大帧率
获取摄像头的参数并填入UI控件中
void MainWindow::SetFrameResolution()
{
mResSize.clear();
mResSize = m_camera->supportedViewfinderResolutions();
ui->cmb_Resolution->clear();
int i=0;
foreach (QSize msize, mResSize) {
qDebug()<<msize;
ui->cmb_Resolution->addItem(QString::number(msize.width(),10)+"*"+QString::number(msize.height(),10), i++);
} //摄像头支持分辨率打印
ui->cmb_Resolution->setCurrentIndex(0);
mMaxFrame.clear();
int j;
for(j=0;j< m_camera->supportedViewfinderFrameRateRanges().length();j++)
{
qreal frameRates = m_camera->supportedViewfinderFrameRateRanges().at(j).maximumFrameRate;
mMaxFrame.append(frameRates);
ui->cmb_MaxFrameRate->addItem(QString::number(frameRates));
}
ui->cmb_MaxFrameRate->setCurrentIndex(j-1);
}
4.显示视频和抓图操作
显示视频时可以把捕捉模式设置为静态帧或视频,目前这两种看起来显示效果没差别,如果有大佬知道可以评论告知区别;
m_camera = new QCamera(this);//初始化摄像头设备
m_camera->setCaptureMode(QCamera::CaptureStillImage);//设置捕捉模式为静态帧
// m_camera->setCaptureMode(QCamera::CaptureVideo);//设置捕捉模式为视频
m_camera->setViewfinder(ui->widgetCamera);//设置 摄像头画面的显示位置
image_capture = new QCameraImageCapture(m_camera);
m_camera->start();//开启摄像头
connect(image_capture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(processCapturedImage(int, QImage)));
timer_image_capture = new QTimer(this);
connect(timer_image_capture,&QTimer::timeout,this,&MainWindow::captureImage);
SetFrameResolution();
三、功能实现代码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCamera>
#include <QCameraImageCapture>
#include <QTimer>
#include <QCameraInfo>
#include <QLabel>
#include <QDateTime>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
// void on_btnCameraCtrl_clicked();
void on_btnSnap_clicked();
void on_btnVedio_clicked();
void processCapturedImage(int request_id, const QImage &img);
void captureImage();
void on_cmb_CameraName_activated(int index);
void on_cmb_Resolution_activated(int index);
void on_cmb_MaxFrameRate_activated(int index);
private:
Ui::MainWindow *ui;
QList<QCameraInfo> cameras;
QCamera* m_camera;//摄像头设备
QCameraImageCapture* image_capture;
QTimer *timer_image_capture;//图像抓图
QList<QSize> mResSize = {};//分辨率List
QList<qreal> mMaxFrame = {};//最大帧率
QTimer *myTimer;//状态栏时间显示
//相机状态标志量参数
QLabel * m_status1;
QLabel * m_status2;
QLabel * m_status3;
void initCamera();
void initForm();
void SetFrameResolution();
void UpdateCameraStatus();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->initCamera();
this->initForm();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initCamera()
{
cameras = QCameraInfo::availableCameras();//获取可用摄像头设备列表
int index = cameras.size();
for(int i=0;i<index;i++)
{
qDebug()<<index<<cameras.at(i).description();//摄像头的设备名称
ui->cmb_CameraName->addItem(cameras.at(i).description());
}
m_camera = new QCamera(this);//初始化摄像头设备
m_camera->setCaptureMode(QCamera::CaptureStillImage);//设置捕捉模式为静态帧
// m_camera->setCaptureMode(QCamera::CaptureVideo);//设置捕捉模式为视频
m_camera->setViewfinder(ui->widgetCamera);//设置 摄像头画面的显示位置
image_capture = new QCameraImageCapture(m_camera);
m_camera->start();//开启摄像头
connect(image_capture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(processCapturedImage(int, QImage)));
timer_image_capture = new QTimer(this);
connect(timer_image_capture,&QTimer::timeout,this,&MainWindow::captureImage);
SetFrameResolution();
}
void MainWindow::initForm()
{
myTimer=new QTimer(this);
myTimer->start(1000);
QLabel * btn = new QLabel(this);
connect(myTimer , &QTimer::timeout, [=](){
QDateTime Date_Time =QDateTime::currentDateTime();
QString Time_system = Date_Time.toString("yyyy-MM-dd hh:mm:ss ddd");
btn->setText(Time_system);
});
// statusBar()->setStyleSheet(QString("QStatusBar::item{border: 2px}"));
statusBar()->setSizeGripEnabled(false);
ui->statusBar->addPermanentWidget(btn);
m_status1 = new QLabel(this);
m_status1->setGeometry(2,2,18,18);
m_status2 = new QLabel(this);
m_status3 = new QLabel(this);
UpdateCameraStatus();
}
void MainWindow::UpdateCameraStatus()
{
QString curCamName = ui->cmb_CameraName->currentText();
QString curCamFrame = ui->cmb_MaxFrameRate->currentText();
QString curCamRes = ui->cmb_Resolution->currentText();
m_status1->setText("摄像头:"+curCamName);
ui->statusBar->addWidget(m_status1);
m_status2->setText("帧率:"+curCamFrame);
ui->statusBar->addWidget(m_status2);
m_status3->setText("分辨率:"+curCamRes);
ui->statusBar->addWidget(m_status3);
}
void MainWindow::on_btnSnap_clicked()
{
image_capture->capture();
}
void MainWindow::on_btnVedio_clicked()
{
int Intervalue = ui->spinBox->value();
timer_image_capture->setInterval(Intervalue);
timer_image_capture->start();
}
void MainWindow::processCapturedImage(int request_id, const QImage &img)
{
QImage scaledImage = img.scaled(ui->label->size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
ui->label->setPixmap(QPixmap::fromImage(scaledImage));
}
void MainWindow::captureImage()
{
image_capture->capture();
}
void MainWindow::on_cmb_CameraName_activated(int index)
{
index = ui->cmb_CameraName->currentIndex();
qDebug()<<"Index"<< index <<": "<< ui->cmb_CameraName->currentText();
if(m_camera->isAvailable())
{
m_camera->stop();
delete m_camera;
}
m_camera = new QCamera(cameras[index]);
m_camera->setCaptureMode(QCamera::CaptureStillImage);
m_camera->setViewfinder(ui->widgetCamera);
image_capture = new QCameraImageCapture(m_camera);
m_camera->start();
connect(image_capture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(processCapturedImage(int, QImage)));
SetFrameResolution();
UpdateCameraStatus();
}
void MainWindow::SetFrameResolution()
{
mResSize.clear();
mResSize = m_camera->supportedViewfinderResolutions();
ui->cmb_Resolution->clear();
int i=0;
foreach (QSize msize, mResSize) {
qDebug()<<msize;
ui->cmb_Resolution->addItem(QString::number(msize.width(),10)+"*"+QString::number(msize.height(),10), i++);
} //摄像头支持分辨率打印
ui->cmb_Resolution->setCurrentIndex(0);
mMaxFrame.clear();
int j;
for(j=0;j< m_camera->supportedViewfinderFrameRateRanges().length();j++)
{
qreal frameRates = m_camera->supportedViewfinderFrameRateRanges().at(j).maximumFrameRate;
mMaxFrame.append(frameRates);
ui->cmb_MaxFrameRate->addItem(QString::number(frameRates));
}
ui->cmb_MaxFrameRate->setCurrentIndex(j-1);
}
void MainWindow::on_cmb_Resolution_activated(int index)
{
index = ui->cmb_Resolution->currentIndex();
qDebug()<<"Index"<< index <<": "<< ui->cmb_Resolution->currentText();
qDebug()<<"mResSize:"<<mResSize[index];
//设置摄像头分辨率
QCameraViewfinderSettings set;
set.setResolution(mResSize[index]);
m_camera->setViewfinderSettings(set);
UpdateCameraStatus();
}
void MainWindow::on_cmb_MaxFrameRate_activated(int index)
{
index = ui->cmb_MaxFrameRate->currentIndex();
//设置摄像头最大帧率
QCameraViewfinderSettings set;
set.setMaximumFrameRate(mMaxFrame[index]);
m_camera->setViewfinderSettings(set);
UpdateCameraStatus();
}
四、源码下载
源码下载:多摄像头显示源码
总结
这里实现了多个相机的视频显示、参数设置和抓图操作,也可以在初始化中使用QList来初始化所有的摄像头并用控件显示,这样就可以同时显示所有摄像头的视频。但是也有部分功能需要进一步研究优化
- 1.使用QCameraImageCapture类发送的capture的信号,系统会默认保存抓取的图像保存到电脑默认路径,一般在C盘下图片这个文件夹下,如果连续采图会导致本地缓存爆炸增长
- 2.在实际项目中,一般要采集到图像进行图像操作后再显示,不是单独去实现视频显示,这里需要使用QAbstractVideoSurface捕获视频帧,进行图像处理后再使用QPainter画到显示控件。