#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtMultimedia>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QMediaCaptureSession *session; //抓取管理器
QCamera *camera; //摄像头
QImageCapture *imageCapture; //抓图器
QSoundEffect *soundEffect; //用于拍照时播放快门音效
QMediaRecorder *recorder; //录像
QLabel *labDuration; //用于状态栏显示信息
QLabel *labInfo;
QLabel *labFormatInfo;
bool m_isWorking=false; //是否已开启摄像头
// void iniCamera();//初始化
// void iniImageCapture();//初始化静态画图
// void iniVideoRecorder();//初始化视频录制
void showCameraDeviceInfo(QCameraDevice *device);
void showCameraSupportFeatures(QCamera *aCamera);
void closeEvent(QCloseEvent *event);
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void do_camera_changed(int index); //与摄像头下拉列表框的信号关联
//与QCamera的信号关联
void do_camera_activeChanged(bool active);
//与QImageCapture的信号关联
void do_image_readyForCapture(bool ready);
void do_image_captured(int id, const QImage &preview);
void do_image_saved(int id, const QString &fileName);
//与QMediaRecorder的信号关联
void do_recorder_duration(qint64 duration);
void do_recorder_stateChanged(QMediaRecorder::RecorderState state);
void do_recorder_error(QMediaRecorder::Error error, const QString &errorString);
void on_actStartCamera_triggered();
void on_actStopCamera_triggered();
void on_actCapture_triggered();
void on_actVideoRecord_triggered();
void on_actVideoStop_triggered();
void on_btnVideoFile_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
该代码是一个使用Qt框架的主窗口类MainWindow的头文件。主要实现了摄像头的初始化、抓图、录像等功能。
在头文件中,定义了以下私有成员变量:
session
:抓取管理器camera
:摄像头imageCapture
:抓图器soundEffect
:用于拍照时播放快门音效recorder
:录像labDuration
:用于状态栏显示信息的标签labInfo
:显示摄像头设备信息的标签labFormatInfo
:显示摄像头支持的特性信息的标签m_isWorking
:判断是否已开启摄像头的标志位
此外,还声明了一些私有函数和私有槽函数,包括:
showCameraDeviceInfo
:显示摄像头设备信息showCameraSupportFeatures
:显示摄像头支持的特性信息do_camera_changed
:与摄像头下拉列表框的信号关联的槽函数do_camera_activeChanged
:与QCamera的信号activeChanged
关联的槽函数do_image_readyForCapture
:与QImageCapture的信号readyForCapture
关联的槽函数do_image_captured
:与QImageCapture的信号imageCaptured
关联的槽函数do_image_saved
:与QImageCapture的信号imageSaved
关联的槽函数do_recorder_duration
:与QMediaRecorder的信号durationChanged
关联的槽函数do_recorder_stateChanged
:与QMediaRecorder的信号stateChanged
关联的槽函数do_recorder_error
:与QMediaRecorder的信号error
关联的槽函数
最后声明了MainWindow类本身,继承自QMainWindow类,并定义了构造函数和析构函数。
在头文件中还存在一些注释掉的函数,可能是用于初始化摄像头、抓图、录像等功能的函数,可以根据需要进行调整或使用。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QSoundEffect>
//void MainWindow::iniCamera()
//{// 创建 QCamera对象
//}
//void MainWindow::iniImageCapture()
//{//创建 QCameraImageCapture对象
//}
//void MainWindow::iniVideoRecorder()
//{//创建QMediaRecorder对象
//}
void MainWindow::showCameraDeviceInfo(QCameraDevice *device)
{//显示摄像头设备信息
ui->comboCam_Position->setCurrentIndex(device->position()); //摄像头位置
ui->comboCam_PhotoRes->clear(); //支持的拍照分辨率
ui->comboImage_Resolution->clear(); //拍照使用的分辨率
foreach(QSize size, device->photoResolutions())
{
QString str=QString::asprintf("%d X %d",size.width(),size.height());
ui->comboCam_PhotoRes->addItem(str); //支持的拍照分辨率
ui->comboImage_Resolution->addItem(str,size); //拍照使用的分辨率,添加QSize用户数据
}
ui->comboCam_VideoRes->clear(); //支持的视频分辨率
ui->comboCam_FrameRate->clear(); //支持的帧率范围
ui->comboVideo_Resolution->clear(); //录像用的分辨率
foreach(QCameraFormat format, device->videoFormats())
{
QSize size=format.resolution();
QString str=QString::asprintf("%d X %d",size.width(),size.height());
ui->comboCam_VideoRes->addItem(str);
ui->comboVideo_Resolution->addItem(str,size); //添加QSize用户数据
str=QString::asprintf("%.1f ~ %.1f",format.minFrameRate(),format.maxFrameRate());
ui->comboCam_FrameRate->addItem(str);
}
}
void MainWindow::showCameraSupportFeatures(QCamera *aCamera)
{//显示摄像头支持的特性
QCamera::Features features= aCamera->supportedFeatures();
bool supported=features.testFlag(QCamera::Feature::ColorTemperature);
ui->chkBoxCam_Color->setChecked(supported);
supported=features.testFlag(QCamera::Feature::ExposureCompensation);
ui->chkBoxCam_Exposure->setChecked(supported);
supported=features.testFlag(QCamera::Feature::IsoSensitivity);
ui->chkBoxCam_Iso->setChecked(supported);
supported=features.testFlag(QCamera::Feature::CustomFocusPoint);
ui->chkBoxCam_Custom->setChecked(supported);
supported=features.testFlag(QCamera::Feature::ManualExposureTime);
ui->chkBoxCam_Manual->setChecked(supported);
supported=features.testFlag(QCamera::Feature::FocusDistance);
ui->chkBoxCam_Focus->setChecked(supported);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (m_isWorking)
{
if(recorder->recorderState() == QMediaRecorder::RecordingState) //正在录制视频
recorder->stop(); //停止录制视频
camera->stop(); //关闭摄像头
}
event->accept();
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
labDuration=new QLabel("录制时间: ");
labDuration->setMinimumWidth(120);
ui->statusBar->addWidget(labDuration);
labFormatInfo=new QLabel("图片分辨率: ");
labFormatInfo->setMinimumWidth(150);
ui->statusBar->addWidget(labFormatInfo);
labInfo=new QLabel("信息");
ui->statusBar->addPermanentWidget(labInfo);
//1. 发现摄像头
QCameraDevice defaultCameraDevice= QMediaDevices::defaultVideoInput();
if (defaultCameraDevice.isNull())
{
QMessageBox::critical(this,"提示","没有发现摄像头");
return;
}
QByteArray defaultCameraID=defaultCameraDevice.id();
ui->actStartCamera->setEnabled(true);
// disconnect(ui->comboCam_List); //解除与comboCam_List连接的所有槽函数
int index=0;
for(int i=0; i<QMediaDevices::videoInputs().size(); i++)
{
QCameraDevice device=QMediaDevices::videoInputs().at(i);
if (device.id() == defaultCameraID)
{
ui->comboCam_List->addItem(device.description()+"(默认)",QVariant::fromValue(device));
index=i;
}
else
ui->comboCam_List->addItem(device.description(),QVariant::fromValue(device));
}
if (ui->comboCam_List->currentIndex() != index)
ui->comboCam_List->setCurrentIndex(index);
// foreach(QCameraDevice device, QMediaDevices::videoInputs())
// {
// if (device.isDefault()) //是默认设备
// ui->comboCam_List->addItem(device.description()+"(默认)",QVariant::fromValue(device));
// else
// ui->comboCam_List->addItem(device.description(),QVariant::fromValue(device));
// }
// ui->comboCam_List->addItem(cameraDevice.description());
// showCameraDeviceInfo(&cameraDevice);
// ui->comboCam_List->addItem(cameraDevice.description());
//2. 创建抓取管理器session和各个设备
session = new QMediaCaptureSession(this); //抓取管理器
session->setVideoOutput(ui->videoPreview); //设置视频输出组件,用于视频预览
//2.1 创建QAudioInput对象,用用音频输入
QAudioInput *audioInput=new QAudioInput(this);
audioInput->setDevice(QMediaDevices::defaultAudioInput());
session->setAudioInput(audioInput); //设置音频输入设备
//2.2 创建QCamera对象,用于控制摄像头
camera = new QCamera(this); //摄像头
camera->setCameraDevice(defaultCameraDevice); //
session->setCamera(camera); //为session设置摄像头
connect(camera, &QCamera::activeChanged,this, &MainWindow::do_camera_activeChanged);
connect(ui->comboCam_List,&QComboBox::currentIndexChanged,
this, &MainWindow::do_camera_changed);
do_camera_changed(ui->comboCam_List->currentIndex());
//2.3 创建QImageCapture对象,用于拍照
imageCapture = new QImageCapture(this); //抓图器
imageCapture->setQuality(QImageCapture::VeryHighQuality);
session->setImageCapture(imageCapture); //为session设置抓图器
connect(imageCapture,&QImageCapture::readyForCaptureChanged,
this, &MainWindow::do_image_readyForCapture);
connect(imageCapture,&QImageCapture::imageCaptured,
this,&MainWindow::do_image_captured);
connect(imageCapture, &QImageCapture::imageSaved,
this, &MainWindow::do_image_saved);
soundEffect =new QSoundEffect(this); //用于播放音效,拍照时的快门声音
QString filename=":/sound/images/shutter.wav";
soundEffect->setSource(QUrl::fromLocalFile(filename));
//2.4 创建QMediaRecorder对象,用于录制视频
recorder = new QMediaRecorder(this); //创建recorder
session->setRecorder(recorder); //为session设置recorder
connect(recorder, &QMediaRecorder::durationChanged,
this, &MainWindow::do_recorder_duration);
connect(recorder, &QMediaRecorder::recorderStateChanged,
this, &MainWindow::do_recorder_stateChanged);
connect(recorder, &QMediaRecorder::errorOccurred,
this, &MainWindow::do_recorder_error);
//3. 视频编码和文件格式,添加到录像设置的下拉列表框里,用于选择
QMediaFormat format;
foreach(QMediaFormat::VideoCodec codec, format.supportedVideoCodecs(QMediaFormat::Encode))
ui->comboVideo_Codec->addItem(QMediaFormat::videoCodecDescription(codec),
QVariant::fromValue(codec));
foreach(QMediaFormat::FileFormat fileFormat, format.supportedFileFormats(QMediaFormat::Encode))
ui->comboVideo_FileFormat->addItem(QMediaFormat::fileFormatDescription(fileFormat),
QVariant::fromValue(fileFormat));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::do_camera_activeChanged(bool active)
{//摄像头状态变化
ui->actStartCamera->setEnabled(!active);
ui->actStopCamera->setEnabled(active);
ui->actVideoRecord->setEnabled(active);
ui->comboCam_List->setEnabled(!active);
m_isWorking = active;
}
void MainWindow::do_image_readyForCapture(bool ready)
{//与 readyForCaptureChanged()信号关联
ui->actCapture->setEnabled(ready);
}
void MainWindow::do_image_captured(int id, const QImage &preview)
{//与 imageCaptured()信号关联
Q_UNUSED(id);
// QSize size=imageCapture->resolution(); //被设置了,但是不起作用, Qt 6.2.2的 bug
// QString str=QString::asprintf("实际图片分辨率= %d X %d",size.width(),size.height());
QString str=QString::asprintf("实际图片分辨率= %d X %d",preview.width(),preview.height());
labFormatInfo->setText(str);
QImage scaledImage = preview.scaledToWidth(ui->scrollArea->width()-30);
ui->labImage->setPixmap(QPixmap::fromImage(scaledImage));
if(! ui->chkBox_SaveToFile->isChecked())
labInfo->setText("图片未保存为文件");
}
void MainWindow::do_image_saved(int id, const QString &fileName)
{//与 imageSaved()信号关联
Q_UNUSED(id);
labInfo->setText("图片保存为文件: "+fileName);
}
void MainWindow::do_recorder_duration(qint64 duration)
{//与 durationChanged()信号关联
labDuration->setText(QString::asprintf("录制时间:%.1f 秒 ",duration/1000.0));
}
void MainWindow::do_recorder_stateChanged(QMediaRecorder::RecorderState state)
{//与 recorderStateChanged()信号关联
ui->actVideoRecord->setEnabled(state == QMediaRecorder::StoppedState);
ui->actVideoStop->setEnabled(state == QMediaRecorder::RecordingState);
}
void MainWindow::do_recorder_error(QMediaRecorder::Error error, const QString &errorString)
{//与 errorOccurred()信号关联
Q_UNUSED(error);
labInfo->setText(errorString);
}
void MainWindow::on_actStartCamera_triggered()
{//开启摄像头
camera->start();
}
void MainWindow::on_actStopCamera_triggered()
{//关闭摄像头
if (recorder->recorderState() == QMediaRecorder::RecordingState)
recorder->stop(); //停止录像
camera->stop();
}
void MainWindow::on_actCapture_triggered()
{//"拍照" 按钮
int index=ui->comboImage_Quality->currentIndex();
imageCapture->setQuality(QImageCapture::Quality(index)); //图片文件编码品质
index=ui->comboImage_Resolution->currentIndex();
QVariant var=ui->comboImage_Resolution->itemData(index); //用户数据
imageCapture->setResolution(var.toSize()); //设置分辨率
// imageCapture->setResolution(640, 480); //直接设置也不起作用,是Qt 6.2.2中的bug
if (ui->chkBox_SaveToFile->isChecked())
imageCapture->captureToFile(); //拍照并保存到文件
else
imageCapture->capture(); //拍照
if (ui->chkBox_Sound->isChecked())
soundEffect->play(); //播放快门音效
ui->tabWidget->setCurrentIndex(0);
}
void MainWindow::on_actVideoRecord_triggered()
{//"开始录像"按钮
QString selectedFile=ui->editVideo_OutputFile->text().trimmed();
if (selectedFile.isEmpty())
{
QMessageBox::critical(this,"错误","请先设置录像输出文件");
return;
}
if (QFile::exists(selectedFile))
if (!QFile::remove(selectedFile))
{
QMessageBox::critical(this,"错误","所设置录像输出文件被占用,无法删除");
return;
}
recorder->setEncodingMode(QMediaRecorder::ConstantQualityEncoding); //按固定品质编码
int index =ui->comboViedo_Quality->currentIndex();
recorder->setQuality(QMediaRecorder::Quality(index)); //编码品质
//设置媒介格式
QMediaFormat mediaFormat;
index=ui->comboVideo_Codec->currentIndex();
QVariant var= ui->comboVideo_Codec->itemData(index); //获取用户数据
QMediaFormat::VideoCodec codec=var.value<QMediaFormat::VideoCodec>();
mediaFormat.setVideoCodec(codec); //设置视频编码
index=ui->comboVideo_FileFormat->currentIndex();
var=ui->comboVideo_FileFormat->itemData(index);
QMediaFormat::FileFormat fileFormat=var.value<QMediaFormat::FileFormat>();
mediaFormat.setFileFormat(fileFormat); //设置文件格式
recorder->setMediaFormat(mediaFormat); //设置媒介格式
index=ui->comboVideo_Resolution->currentIndex();
var=ui->comboVideo_Resolution->itemData(index); //获取用户数据
recorder->setVideoResolution(var.toSize()); //设置视频分辨率
labInfo->clear();
recorder->setOutputLocation(QUrl::fromLocalFile(selectedFile)); //设置输出文件
recorder->record();
}
void MainWindow::on_actVideoStop_triggered()
{//停止录像
recorder->stop();
}
void MainWindow::on_btnVideoFile_clicked()
{
QString curPath=QDir::homePath();
QString dlgTitle="选择保存文件";
QString filter="MP4视频文件(*.mp4);;WMV视频文件(*.wmv);;所有文件(*.*)";
QString selectedFile=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (!selectedFile.isEmpty())
ui->editVideo_OutputFile->setText(selectedFile);
}
void MainWindow::do_camera_changed(int index)
{
QVariant var=ui->comboCam_List->itemData(index);
QCameraDevice device = var.value<QCameraDevice>();
showCameraDeviceInfo(&device); //显示摄像头设备信息
camera->setCameraDevice(device); //重新设置摄像头设备
showCameraSupportFeatures(camera); //显示摄像头支持的特性
}
这段代码是一个基于Qt框架的摄像头应用程序的主窗口类的实现。主要功能包括显示摄像头设备信息、显示摄像头支持的特性、开启和关闭摄像头、拍照和录制视频等。
在构造函数中,进行了以下操作:
-
发现摄像头:使用QMediaDevices::defaultVideoInput()获取默认摄像头设备,如果没有找到摄像头则提示用户没有发现摄像头。
-
创建抓取管理器session和各个设备:
- 创建QAudioInput对象用于音频输入,并设置音频输入设备。
- 创建QCamera对象用于控制摄像头,并设置默认摄像头设备为当前选择的摄像头设备。连接camera的activeChanged信号与槽函数do_camera_activeChanged。
- 创建QImageCapture对象用于拍照,并设置抓图质量为VeryHighQuality。连接imageCapture的readyForCaptureChanged、imageCaptured和imageSaved信号与相应的槽函数。
- 创建QMediaRecorder对象用于录制视频,并设置录像相关的信号和槽函数。
-
视频编码和文件格式:将支持的视频编码和文件格式添加到录像设置的下拉列表框中,供用户选择。
在析构函数中,释放UI资源。
其他成员函数包括:
- showCameraDeviceInfo:显示摄像头设备信息,包括位置、支持的拍照分辨率和视频分辨率等。
- showCameraSupportFeatures:显示摄像头支持的特性,包括颜色温度、曝光补偿、ISO感光度等。
- closeEvent:处理窗口关闭事件,停止录制视频并关闭摄像头。
- do_camera_activeChanged:处理摄像头状态变化,更新界面按钮状态。
- do_image_readyForCapture:处理readyForCaptureChanged信号,更新界面按钮状态。
- do_image_captured:处理imageCaptured信号,显示拍照的图片和实际图片分辨率。
- do_image_saved:处理imageSaved信号,显示图片保存的文件名。
- do_recorder_duration:处理durationChanged信号,更新录制时间显示。
- do_recorder_stateChanged:处理recorderStateChanged信号,更新录制按钮的状态。
- do_recorder_error:处理errorOccurred信号,显示错误信息。
-
槽函数:
do_camera_activeChanged
:摄像头状态变化时更新界面元素的可用性。do_image_readyForCapture
:在可以进行拍照时启用拍照按钮。do_image_captured
:拍照后显示预览图片和分辨率信息。do_image_saved
:保存图片后显示保存文件的信息。do_recorder_duration
:更新录制时间显示。do_recorder_stateChanged
:根据录制器状态更新界面元素的可用性。do_recorder_error
:处理录制器错误并显示错误信息。
-
其他函数:
on_actStartCamera_triggered
:启动摄像头。on_actStopCamera_triggered
:停止摄像头,如果正在录制视频,则同时停止录制。on_actCapture_triggered
:拍照,根据用户选择设置图片质量和分辨率。on_actVideoRecord_triggered
:开始录制视频,根据用户选择设置视频质量、编码格式和分辨率。on_actVideoStop_triggered
:停止录制视频。on_btnVideoFile_clicked
:选择视频保存文件的路径。