当前位置: 首页 > news >正文

【QT常用技术讲解】multimedia实现指定分辨率打开摄像头

前言

        摄像头是很常见的外设,本文分享的是通用QT自带的多媒体模块来操作摄像头,本应用支持选择摄像头,选择摄像头的分辨率,打开/关闭摄像头。

效果图

功能讲解

摄像头下拉框

内容包括3大要素:摄像头序号、摄像头名称、摄像头的VIDPID。相关的代码如下:

void MainWindow::getcamerainfo() {qDebug() << __FUNCTION__;ui->comboBox->clear();cameralist.clear();// 断开之前的连接,避免重复连接disconnect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::on_camera_selection_changed);cameras = QCameraInfo::availableCameras();if (cameras.isEmpty()) {qWarning() << "No cameras found.";QMessageBox::information(this, "提醒", "未检测到摄像头设备");return;}int num = 0;for (const QCameraInfo &cameraInfo : cameras) {qDebug() << "Camera deviceName:" << cameraInfo.deviceName();QString vid = getvidpid("vid_", cameraInfo.deviceName());QString pid = getvidpid("pid_", cameraInfo.deviceName());qDebug() << "Camera name:" << cameraInfo.description() << " vid:" << vid << " pid:" << pid;QString camarastr = QString::number(num) + ". " + cameraInfo.description() + "(" + vid + ":" + pid + ")";cameralist.append(camarastr);ui->comboBox->addItem(camarastr);num++;}// 如果有摄像头,默认选择第一个并获取其分辨率if (ui->comboBox->count() > 0) {// 手动调用分辨率获取函数,而不是通过信号触发QTimer::singleShot(100, [this]() {int index = ui->comboBox->currentIndex();if (index >= 0 && index < cameras.size()) {QCameraInfo cameraInfo = cameras.at(index);updateResolutionComboBox(cameraInfo);}});}
}

在初始化函数中,调用以上函数

分辨率下拉框

QList<QSize> MainWindow::getSupportedResolutions(const QCameraInfo &cameraInfo) {QList<QSize> resolutions;// 创建临时摄像头对象获取分辨率QCamera tempCamera(cameraInfo);// 使用QEventLoop等待摄像头加载完成QEventLoop loop;QTimer timer;timer.setSingleShot(true);QObject::connect(&tempCamera, &QCamera::stateChanged, [&](QCamera::State state) {if (state == QCamera::LoadedState) {loop.quit();}});QObject::connect(&timer, &QTimer::timeout, [&]() {if (loop.isRunning()) {qWarning() << "Camera loading timed out";loop.quit();}});tempCamera.load();timer.start(2000); // 2秒超时loop.exec();if (tempCamera.state() == QCamera::LoadedState) {QList<QCameraViewfinderSettings> supportedSettings = tempCamera.supportedViewfinderSettings();if (supportedSettings.isEmpty()) {qWarning() << "No supported viewfinder settings for camera:" << cameraInfo.description();// 备用方法:尝试通过图像捕获获取分辨率QCameraImageCapture imageCapture(&tempCamera);QList<QSize> imageResolutions = imageCapture.supportedResolutions();if (!imageResolutions.isEmpty()) {resolutions = imageResolutions;} else {// 提供一些常见分辨率作为备选resolutions << QSize(640, 480)<< QSize(800, 600)<< QSize(1024, 768)<< QSize(1280, 720)<< QSize(1920, 1080);}} else {// 提取分辨率并手动去重(不使用QSet)for (const QCameraViewfinderSettings &setting : supportedSettings) {if (setting.resolution().isValid() &&setting.resolution().width() > 0 &&setting.resolution().height() > 0) {// 检查是否已存在相同分辨率bool alreadyExists = false;for (const QSize &existing : resolutions) {if (existing == setting.resolution()) {alreadyExists = true;break;}}if (!alreadyExists) {resolutions.append(setting.resolution());}}}}// 按面积排序(从小到大)std::sort(resolutions.begin(), resolutions.end(), [](const QSize &a, const QSize &b) {return a.width() * a.height() < b.width() * b.height();});} else {qWarning() << "Failed to load camera for resolution detection:" << cameraInfo.description();// 提供一些默认分辨率resolutions << QSize(640, 480)<< QSize(800, 600)<< QSize(1024, 768)<< QSize(1280, 720)<< QSize(1920, 1080);}tempCamera.unload();return resolutions;
}void MainWindow::updateResolutionComboBox(const QCameraInfo &cameraInfo) {qDebug() << "Updating resolution combo box for camera:" << cameraInfo.description();// 在状态栏显示加载信息statusBar()->showMessage("正在获取摄像头支持的分辨率...");// 使用单次定时器异步获取分辨率,避免界面卡顿QTimer::singleShot(100, [this, cameraInfo]() {QList<QSize> resolutions = getSupportedResolutions(cameraInfo);ui->comboBox_resolution->clear();if (resolutions.isEmpty()) {ui->comboBox_resolution->addItem("默认分辨率");statusBar()->showMessage("无法获取分辨率列表,将使用默认分辨率", 3000);} else {for (const QSize &resolution : resolutions) {QString resText = QString("%1 x %2").arg(resolution.width()).arg(resolution.height());ui->comboBox_resolution->addItem(resText, resolution);}statusBar()->showMessage(QString("找到 %1 个支持的分辨率").arg(resolutions.size()), 3000);}});
}void MainWindow::on_camera_selection_changed(int index) {if (index < 0 || index >= cameras.size()) return;ui->comboBox_resolution->clear();// 获取选中的摄像头QCameraInfo cameraInfo = cameras.at(index);updateResolutionComboBox(cameraInfo);
}

在初始化函数中引用

// 连接摄像头选择变化信号connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::on_camera_selection_changed);

打开摄像头

void MainWindow::on_btn_open_clicked() {if (camera != nullptr) return;if (cameralist.size() < 1) {QMessageBox::information(this, "提醒", "摄像头不存在");return;}int cameraNo = ui->comboBox->currentIndex();QCameraInfo cameraInfo = cameras.at(cameraNo);qDebug() << "Opening camera" << cameraNo << cameraInfo.description();// 创建摄像头对象camera = new QCamera(cameraInfo, this);if (!camera->isAvailable()) {qWarning() << "Camera is not available.";QMessageBox::warning(this, "错误", "摄像头不可用");delete camera;camera = nullptr;return;}// 设置分辨率(如果用户选择了特定分辨率)if (ui->comboBox_resolution->currentIndex() > 0) {QSize selectedResolution = ui->comboBox_resolution->currentData().toSize();if (selectedResolution.isValid()) {QCameraViewfinderSettings settings;settings.setResolution(selectedResolution);camera->setViewfinderSettings(settings);qDebug() << "Set resolution to:" << selectedResolution;}}// 创建视图查找器viewfinder = new QCameraViewfinder();//让摄像头画面自适应填充整个widget_video区域viewfinder->setAspectRatioMode(Qt::IgnoreAspectRatio);  // 忽略原始宽高比viewfinder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);camera->setViewfinder(viewfinder);// 清除之前的布局if (ui->widget_video->layout()) {delete ui->widget_video->layout();}// 创建新布局并添加视图查找器layout = new QVBoxLayout;layout->addWidget(viewfinder);ui->widget_video->setLayout(layout);// 开始预览camera->start();status = true;
}

以上通过视图查找器预览摄像头的内容,增加了一下两行代码,让摄像头画面自适应填充整个显示区域:

viewfinder->setAspectRatioMode(Qt::IgnoreAspectRatio);  // 忽略原始宽高比viewfinder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

去掉以上代码,则按照原来的分辨率大小进行显示。

关闭摄像头

void MainWindow::on_btn_close_clicked() {if (camera == nullptr) return;camera->stop();// 清除布局if (ui->widget_video->layout()) {QLayoutItem *item;while ((item = ui->widget_video->layout()->takeAt(0)) != nullptr) {delete item->widget();delete item;}delete ui->widget_video->layout();}delete camera;camera = nullptr;status = false;}

篇尾

        QT自带的媒体模块,适合处理一些常用的功能,后续也分享使用opencv方式实现相同的功能。

http://www.dtcms.com/a/445923.html

相关文章:

  • 阿里巴巴网站的搜索引擎优化案例邢台做网站的价格究竟多少钱?
  • 一个学校随机点名系统(代excel 自定义导入名字,+随机点名)
  • 苍穹外卖-缓存商品、购物车功能
  • 海南住房和城乡建设厅网站首页建站之星怎么使用
  • 番茄畅听音乐版自动化任务实现教程
  • java基础-12 : 单列集合(Collection)
  • 查看邮箱注册过的网站百度资源搜索引擎
  • 网站建设常用编程语言square wordpress
  • 动规:01背包
  • 返利APP的“订单追踪”技术难点:如何通过埋点+消息队列(RocketMQ)实时同步淘宝/京东订单状态?
  • Net开发工具最新Rider 2025使用
  • 基于华为openEuler部署Dillinger个人文本编辑器
  • wordpress 标签固定链接宁波seo网络推广外包报价
  • 网站建设数据库是什么百度一下京东
  • 【Leetcode hot 100】131.分割回文串
  • ARM - GCC - 建立自己的命令行编译环境
  • Nginx限流配置
  • 大岭山做网站九亭做网站公司
  • 微软宣布 Windows 11 v25H2 GA
  • Burp Suite模拟器抓包全攻略
  • 佛山营销型网站定制绿色企业网站源码
  • Qt 5.14.2+Mysql5.7 64位开发环境下无法连接数据库
  • 【Python】
  • [特殊字符]ui设计公司灵感备忘录 | 网格布局 UI 收集
  • Base UI:一款极简主义的「无样式」组件库
  • MySQL 运维知识点(十六)---- 读写分离
  • 网站建设生存期模型希音电商网站
  • 济南网站建设培训班永久免费网站建设
  • 高层次综合报告分析-vivado hls第四章
  • Go语言中的Zap日志库