基于Qt/C++与OpenCV库 实现基于海康相机的图像采集和显示系统(工程源码可联系博主索要)

本文将梳理一个基于 Qt 和 OpenCV 实现的海康相机图像采集 Demo。该程序能够实现相机连接、参数设置、图像采集与显示、异常处理等功能,并通过 Qt 界面展示操作结果。
在这里插入图片描述

1. 功能概述

该程序使用 Qt 的 GUI 作为界面,OpenCV 作为图像处理库,通过海康 MVS SDK 完成对相机的控制。主要功能包括:

  • 相机连接和设置
  • 参数调整(如曝光时间和触发模式)
  • 图像采集与显示
  • 异常处理(如设备断开)

2. 初始化与 GUI 设置

2.1 初始化 GUI

MainWindow 的构造函数中进行界面初始化,包括设置按钮的可见性、禁用状态等。 initStyle() 函数用于加载和应用界面的样式表。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    initStyle();

    // 设置初始 UI 状态
    ui->btn_Start->setEnabled(false);
    ui->btn_Stop->setEnabled(false);
    ui->btn_close->setEnabled(false);
    ui->btn_Grab->setVisible(false);
    ui->groupBox->setEnabled(false);
}

3. 相机连接与操作

3.1 枚举和连接相机

程序通过点击按钮搜索连接的相机设备,并显示在列表中。使用 MV_CC_EnumDevices 函数枚举设备,再通过 MV_CC_CreateHandleMV_CC_OpenDevice 创建并打开相机句柄。

void MainWindow::on_btnSeachCamera_clicked() {
    ui->listWidget->clear();
    int nRet = MV_OK;
    bool isGige = ui->radioGIGE->isChecked();

    // 枚举 PC 连接的所有相机
    if (isGige) {
        if (MV_OK != (nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE, &cameraList))) {
            setLastErrorMsg(tc("未找到可用网口相机, 错误码: %1").arg(nRet));
        }
    } else {
        if (MV_OK != (nRet = MV_CC_EnumDevices(MV_USB_DEVICE, &cameraList))) {
            setLastErrorMsg(tc("未找到可用 USB 相机, 错误码: %1").arg(nRet));
            return;
        }
    }

    // 将相机序列号添加到列表
    for (int i = 0; i < cameraList.nDeviceNum; i++) {
        const char *serial = isGige
                ? reinterpret_cast<char *>(cameraList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber)
                : reinterpret_cast<char *>(cameraList.pDeviceInfo[i]->SpecialInfo.stUsb3VInfo.chSerialNumber);
        ui->listWidget->addItem(serial);
    }
}
3.2 相机参数设置

通过调用 MV_CC_SetExposureTimeMV_CC_SetEnumValue 设置曝光时间和触发模式。使用 Qt 的信号和槽机制,使得调整触发模式和曝光时间变得更加便捷。

void MainWindow::on_comboBox_activated(int index) {
    int nRet = MV_OK;
    switch (index) {
    case OpenContinue:
        nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 0);  // 连续采集
        break;
    case OpenSoftWare:
        nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 1);  // 软件触发模式
        if (MV_OK == nRet) nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 7);
        break;
    case OpenHardWare:
        nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 1);  // 硬件触发模式
        if (MV_OK == nRet) nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 0);
        if (MV_OK == nRet) nRet = MV_CC_SetEnumValue(m_handle, "TriggerActivation", 0);
        break;
    }
    if (MV_OK != nRet) {
        setLastErrorMsg(tc("设置触发模式失败, 错误码: %1").arg(nRet));
    }
}

4. 图像采集与显示

4.1 图像采集回调

通过注册图像回调函数 ImageCallBack,将采集到的图像数据转换为 OpenCV 的 cv::Mat 格式,然后显示在 Qt 的 QLabel 中。

void ImageCallBack(unsigned char *pData, MV_FRAME_OUT_INFO_EX *pFrameInfo, void *pUser) {
    MainWindow *camera = static_cast<MainWindow *>(pUser);

    cv::Mat srcImage;
    switch (pFrameInfo->enPixelType) {
    case PixelType_Gvsp_Mono8:
        srcImage = cv::Mat(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC1, pData);  // 单通道灰度
        break;
    case PixelType_Gvsp_RGB8_Packed:
        RGB2BGR(pData, pFrameInfo->nWidth, pFrameInfo->nHeight);  // RGB 转 BGR
        srcImage = cv::Mat(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3, pData);
        break;
    case PixelType_Gvsp_BayerRG8:
        cv::Mat bayerImage(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC1, pData);
        cv::cvtColor(bayerImage, srcImage, cv::COLOR_BayerRG2BGR);
        break;
    }

    camera->detect(srcImage);  // 显示图像
}

void MainWindow::detect(const cv::Mat &image) {
    ui->lab_image->setPixmap(QPixmap::fromImage(MatToQImage(image)).scaled(ui->lab_image->size()));
}
4.2 图像格式转换

使用 MatToQImage 函数将 OpenCV 的 cv::Mat 格式图像转换为 Qt 的 QImage 格式,以便在 QLabel 中显示。

QImage MatToQImage(const cv::Mat &mat) {
    switch (mat.type()) {
        case CV_8UC1:
            return QImage(mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_Grayscale8).copy();
        case CV_8UC3: {
            cv::Mat rgbMat;
            cv::cvtColor(mat, rgbMat, cv::COLOR_BGR2RGB);  // BGR 转 RGB
            return QImage(rgbMat.data, rgbMat.cols, rgbMat.rows, static_cast<int>(rgbMat.step), QImage::Format_RGB888).copy();
        }
        case CV_8UC4:
            return QImage(mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_ARGB32).copy();
        default:
            throw std::runtime_error("Unsupported Mat format");
    }
}

5. 异常处理与资源释放

5.1 异常处理

程序注册了异常回调函数 ExceptionCallBack,用于处理如设备断开连接的异常情况,并将错误信息显示在界面上。

void ExceptionCallBack(unsigned int nMsgType, void *pUser) {
    if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT) {
        MainWindow *camera = static_cast<MainWindow *>(pUser);
        camera->setLastErrorMsg(tc("相机连接断开"));
    }
}
5.2 资源释放

在退出程序时,需要释放相机资源并关闭设备,以避免内存泄漏。

void MainWindow::on_btn_close_clicked() {
    on_btn_Stop_clicked();  // 停止采集
    int nRet = MV_CC_CloseDevice(m_handle);
    if (MV_OK != nRet) {
        setLastErrorMsg(tc("关闭相机失败, 错误码: %1").arg(nRet));
        return;
    }
}

6. 总结

本代码实现了基于 Qt 和 OpenCV 的相机操作,借助 Qt 的信号槽机制和 OpenCV 的图像处理能力,完成了从相机图像采集到显示的完整流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916171.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络基础Linux

目录 计算机网络背景 网络发展 认识 "协议" 网络协议初识 OSI七层模型 TCP/IP五层(或四层)模型 网络传输基本流程 网络传输流程图 ​编辑 数据包封装和分用 网络中的地址管理 认识IP地址 认识MAC地址 笔记&#xff08;画的图&#xff09; 协议&#x…

大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

性能调优专题(12)之垃圾收集器ParNewCMS与底层三色标记算法详解

一、垃圾收集算法 1.1 分代收集理论 当前虚拟机的垃圾收集器都采用分代收集理论&#xff0c;只是根据对象存活周期的不同将内存分为几块。一般Java将堆分为新生代和老年代&#xff0c;这样子我们就可以根据各个年代的特点选择合适的垃圾收集算法。 比如在新生代中&#xff0c;每…

JAVA学习日记 ArrayList+LinkedList+迭代器源码分析

一、ArrayList 底层原理&#xff1a; ①利用空参构造的集合&#xff0c;在底层创建一共默认长度为0的数组 ②添加第一个元素时&#xff0c;底层会创建一个新的长度为10的数组 ③存满时&#xff0c;会扩容1.5倍 ④如果一次添加多个元素&#xff0c;1.5倍放不下&#xff0c;…

python+pptx:(二)添加图片、表格、形状、模版渲染

目录 图片 表格 合并单元格 填充色、边距 写入数据 形状 模版渲染 上一篇&#xff1a;pythonpptx&#xff1a;&#xff08;一&#xff09;占位符、文本框、段落操作_python输出ppt母版占位符标号-CSDN博客 from pptx import Presentation from pptx.util import Cm, In…

RDIFramework.NET CS敏捷开发框架 V6.1发布(.NET6+、Framework双引擎、全网唯一)

RDIFramework.NET C/S敏捷开发框架V6.1版本迎来重大更新与调整&#xff0c;全面重新设计业务逻辑代码&#xff0c;代码量减少一半以上&#xff0c;开发更加高效。全系统引入全新字体图标&#xff0c;整个界面焕然一新。底层引入最易上手的ORM框架SqlSugar&#xff0c;让开发更加…

力扣经典面试题

1.本题的目标是判断字符串ransomNote是否由字符串magazine中的字符构成&#xff0c;且由magazine中的每个字符只能在ransomNote中使用一次 2.采用的方法是通过一个字典cahr_countl来统计magazine字符串中每个字符出现的次数 3.然后遍历ransomNote字符串&#xff0c;对于其中的…

安卓aosp15手机上如何离线获取winscope文件

背景&#xff1a; 针对winscope在aosp14高版本的抓取环境搭建问题&#xff0c;前面文章已经给大家一篇业界独家干货文章&#xff1a; android 14版本的winscope编译使用-手把手教你编译成功不报错 这篇文章搭建的winscope的方式同样适用于aosp15版本&#xff0c;只需要使用最新…

【机器学习入门】(1) 线性回归算法

学习目标&#xff1a; 线性回归是一种基本的统计学习方法&#xff0c;主要用于分析一个或多个自变量与因变量之间的线性关系。以下是关于线性回归的一些关键点&#xff1a;线性回归的四要素&#xff1a; &#xff08;1&#xff09;假设(hypothesis)&#xff1b;&#xff08;2&…

基于MATLAB身份证号码识别

课题介绍 本课题为基于连通域分割和模板匹配的二代居民身份证号码识别系统&#xff0c;带有一个GUI人机交互界面。可以识别数十张身份证图片。 首先从身份证图像上获取0&#xff5e;9和X共十一个号码字符的样本图像作为后续识别的字符库样本&#xff0c;其次将待测身份证图像…

嵌入式硬件实战提升篇(一)-泰山派RK3566制作多功能小手机

引言&#xff1a;主要针对于嵌入式全栈内容的知识点汇总并对于linux等相关驱动知识点进行串联&#xff0c;用大家参考学习&#xff0c;并用到了嘉立创提供的泰山派RK3566作为学习的主控。 实物演示如下所示&#xff1a; 目录 一、硬件设计 1.转接电路 2.背光电路 3.音频接…

springboot餐厅点餐系统-计算机设计毕业源码14189

目 录 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 餐厅点餐系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 餐厅点餐系统…

制造业7大模式:智能制造、协同制造、绿色制造等思维导图详解

在当今快速变化的市场环境中&#xff0c;制造业正迎来前所未有的变革。从智能工厂的高效运作到网络化制造的全球协同&#xff0c;从云制造的资源共享到3D打印的个性化定制&#xff0c;这些前沿制造模式正在重新定义生产方式&#xff0c;提升企业的竞争力。 今天给大家分享最前沿…

加速 AI 创新:引入 Elastic AI 生态系统

作者&#xff1a;来自 Elastic Alyssa Fitzpatrick, Steve Kearns 生成式人工智能 (Generative AI - GenAI) 正在改变我们所熟知的商业格局。为了简化和加速开发人员构建和部署检索增强生成 (retrieval augmented generation - RAG) 应用程序的方式&#xff0c;Elastic 自豪地宣…

centos rich 美观打印日志

文章目录 步骤 1: 安装 Python 和 pip步骤 2: 安装 rich-cli步骤 3: 验证安装步骤 4: 使用 rich-cli参考 在 CentOS 上安装 rich-cli 工具&#xff0c;你可以按照以下步骤进行操作。rich-cli 是一个命令行工具&#xff0c;用于将 rich 库的功能&#xff08;例如美化输出&#x…

教育行业企业OKR推行实践案例

一、企业背景与推行前痛点 某教育行业企业&#xff0c;专注于提供高质量的在线教育服务&#xff0c;拥有丰富的课程资源和优秀的教师团队。然而&#xff0c;在快速发展过程中&#xff0c;企业面临着一系列挑战&#xff0c;主要包括&#xff1a; 战略目标模糊&#xff1a;企业高…

亚马逊低价商城上线,低价策略能否撬动市场?

经过长达五个多月的筹备&#xff0c;亚马逊终于在其移动端正式推出了备受瞩目的低价商城。11月12日&#xff0c;用户只需在亚马逊APP中搜索“Haul”&#xff0c;即可轻松找到这座充满吸引力的购物殿堂。商城的界面设计简洁直观&#xff0c;其后缀寓意着“以更少的支出&#xff…

【C++】string类(附题)

一、为什么学习string类&#xff1f; 1.1 C语言中的字符串 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列 的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&…

AIHub: 模型和数据集的私有云存储库

AIStor 的最新功能之一是广受欢迎的开源项目 Hugging Face 的私有云版本。这篇文章详细介绍了 AIStor 的 AIHub 如何有效地创建一个完全由企业控制的 API 兼容的私有云版本的 Hugging Face。在我们开始之前&#xff0c;介绍 Hugging Face 是有意义的。Hugging Face 是面向 AI 工…

激增400%!GPS欺骗成全球大患,此题何解?

据网络安全研究人员称&#xff0c;GPS欺骗这种可使商用客机偏离航线的数字攻击形式近期激增400%。数据显示&#xff0c;在今年部分时间里&#xff0c;甚至有多达1350架航班遭遇GPS“欺骗”。 GPS欺骗 — 关键是时间&#xff0c;而不仅仅是位置 GPS系统作为目前使用时间最长、应…