Qt/C++ 海康SDK开发示例Demo

news2024/11/24 8:48:22

*** 工业相机在机器视觉中起到关键作用,本文基于海康 SDK 详细解读了设备连接与控制的各个步骤。内容涵盖设备枚举、句柄创建、图像采集回调以及设备异常处理,帮助开发者快速理解如何通过代码控制相机,实时采集并处理图像数据。***
在这里插入图片描述

在这里插入图片描述

1. 搜索并枚举相机设备

这个部分主要是枚举所有连接的相机设备,并在界面上显示设备的序列号,供用户选择。

void MainWindow::on_btnSeachCamera_clicked() {
    ui->listWidget->clear();  // 清空当前相机列表
    int nRet = MV_OK;
    bool isGige = ui->radioGIGE->isChecked();  // 判断选择的是 GIGE 还是 USB 连接

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

    // 如果没有找到相机,返回提示
    if (cameraList.nDeviceNum == 0) {
        setLastErrorMsg(tc("C10: 未找到任何可用相机"));
        return;
    }

    // 将找到的相机序列号添加到 UI 列表中
    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);
    }
}
  • 主要功能:枚举设备,根据用户选择的接口类型(GIGE或USB),调用 MV_CC_EnumDevices 获取连接到计算机的相机列表。
  • UI 更新:将所有找到的设备序列号添加到列表控件中供用户选择。

2. 创建设备句柄并连接设备

用户在选择相机并点击“连接”按钮后,程序会为选定的相机创建句柄,并尝试连接设备。

void MainWindow::on_btnconnect_clicked() {
    MV_CC_DEVICE_INFO cameraInfo;
    int nRet = MV_OK;
    unsigned int i = 0;  // 假设选择了第一个相机

    // 创建设备句柄
    memcpy(&cameraInfo, cameraList.pDeviceInfo[i], sizeof(MV_CC_DEVICE_INFO));
    nRet = MV_CC_CreateHandle(&m_handle, &cameraInfo);
    if (nRet != MV_OK) {
        setLastErrorMsg(tc("C12: 相机 #%1 初始化失败, 错误码: %2").arg(i).arg(nRet));
        return;
    }

    // 打开设备
    nRet = MV_CC_OpenDevice(m_handle, MV_ACCESS_Exclusive);
    if (nRet != MV_OK) {
        setLastErrorMsg(tc("C14: 相机 #%1 打开失败, 错误码: %2").arg(i).arg(nRet));
        return;
    }

    m_fram = (cameraInfo.nTLayerType == MV_GIGE_DEVICE) ? 0 : -1;
}
  • 创建句柄MV_CC_CreateHandle 函数使用选中的设备信息 cameraInfo 创建相机句柄 m_handle
  • 打开设备:通过 MV_CC_OpenDevice 打开相机,并指定独占模式(MV_ACCESS_Exclusive),避免其他进程访问该设备。
  • 帧计数初始化:如果是网口设备(GIGE),初始化帧计数器 m_fram 为 0;否则设为 -1,表示未初始化。

3. 设置相机触发模式

用户可以通过界面选择不同的触发模式,包括连续采集、软件触发和硬件触发。相机的触发模式会影响图像采集的方式。

void MainWindow::on_comboBox_activated(int index) {
    ui->btn_Grab->setVisible(index == OpenSoftWare);  // 仅在软件触发模式下显示抓拍按钮
    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 (nRet == MV_OK) nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 7);  // 设置触发源为软件
            break;
        case OpenHardWare:  // 硬件触发模式
            nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", 1);
            if (nRet == MV_OK) nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 0);  // 触发源为硬件
            if (nRet != MV_OK) nRet = MV_CC_SetEnumValue(m_handle, "TriggerSource", 1);
            if (nRet == MV_OK) nRet = MV_CC_SetEnumValue(m_handle, "TriggerActivation", 0);  // 触发激活为上升沿
            break;
    }

    if (nRet != MV_OK) {
        setLastErrorMsg(tc("C24: 设置触发模式失败, 错误码: %1").arg(nRet));
    }
}
  • 连续采集:设置触发模式为 0(关闭触发模式),相机会自动连续采集图像。
  • 软件触发:设置触发模式为 1,并将触发源设置为软件触发源(值为 7),之后可以通过代码发送触发命令来抓取图像。
  • 硬件触发:设置触发模式为 1,触发源为硬件触发通道 0 或 1(如硬件引脚输入触发信号)。

4. 图像采集回调函数 - ImageCallBack

每当相机采集到一帧图像时,都会触发 ImageCallBack 回调函数。该函数负责将图像数据转换为 Halcon 格式并显示在 UI 界面中。

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

    // 更新相机图像参数信息到 UI 显示
    camera->ui->lab_W->setText(QString::number(pFrameInfo->nWidth));
    camera->ui->lab_H->setText(QString::number(pFrameInfo->nHeight));
    camera->ui->lab_P->setText(QString::number(pFrameInfo->nFrameNum));
    camera->ui->lab_tri->setText(QString::number(pFrameInfo->nTriggerIndex));

    try {
        HalconCpp::HObject ho_Image;
        int ImageWidth = pFrameInfo->nWidth;
        int ImageHeight = pFrameInfo->nHeight;

        // 根据像素格式生成 Halcon 图像对象
        switch (pFrameInfo->enPixelType) {
            case PixelType_Gvsp_Mono8:
                HalconCpp::GenImage1(&ho_Image, "byte", ImageWidth, ImageHeight, reinterpret_cast<Hlong>(pData));
                break;
            case PixelType_Gvsp_RGB8_Packed:
                HalconCpp::GenImageInterleaved(&ho_Image, reinterpret_cast<Hlong>(pData), "rgb",
                                               ImageWidth, ImageHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                break;
            case PixelType_Gvsp_BayerRG8:
                HalconCpp::GenImage1(&ho_Image, "byte", ImageWidth, ImageHeight, reinterpret_cast<Hlong>(pData));
                HalconCpp::CfaToRgb(ho_Image, &ho_Image, "bayer_rg", "bilinear");
                break;
            default:
                HalconCpp::GenImageConst(&ho_Image, "byte", ImageWidth, ImageHeight);
                break;
        }

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

    } catch (const HalconCpp::HException &) {
        camera->setLastErrorMsg(tc("C25: 相机图像数据格式转换失败"));
    }
}
  • 图像数据转换:根据 pFrameInfo->enPixelType 中的像素类型,调用 Halcon 库的不同函数将图像数据 pData 转换

为 Halcon 图像对象 ho_Image

  • 图像显示:调用 camera->detect(ho_Image); 将转换后的图像显示在 UI 窗口中。
  • 异常处理:若图像数据转换失败,则会记录错误信息。

5. 异常处理回调函数 - ExceptionCallBack

当设备连接断开或发生其他异常情况时,SDK 会调用该异常回调函数。我们可以在此函数中记录并显示错误信息,提示用户相机状态异常。

void ExceptionCallBack(unsigned int nMsgType, void *pUser) {
    if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT) {
        MainWindow *camera = static_cast<MainWindow *>(pUser);
        camera->setLastErrorMsg(tc("C26: 相机连接断开"));
    }
}
  • 主要功能:判断消息类型 nMsgType 是否为设备断开事件 MV_EXCEPTION_DEV_DISCONNECT。若设备断开,程序会调用 setLastErrorMsg 显示错误信息。

总结

这段代码实现了通过海康 SDK 控制工业相机的主要功能,包括设备搜索、创建句柄、设置触发模式、图像采集和异常处理。该流程在实际的机器视觉应用中很常见,适用于产品质量检测、生产线监控等场景。流程概括如下:

  1. 设备枚举:找到并列出所有连接的相机设备,供用户选择。
  2. 创建句柄和连接设备:为选定设备创建句柄并连接设备。
  3. 触发模式设置:支持多种采集模式(如连续采集、软件触发、硬件触发),用户可以根据实际需求选择。
  4. 图像采集回调:采集到图像后触发回调,将图像数据转换为 Halcon 格式并显示。
  5. 异常处理:实时监控设备状态,当设备断开时触发异常回调并记录提示。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ的应用

七种工作模式介绍 1.Simple(简单模式) P&#xff1a;生产者&#xff0c;也就是要发送信息的程序 C&#xff1a;消费者&#xff0c;消息的接收者 Queue&#xff1a;消息队列。图中黄色背景部分&#xff0c;类似一个邮箱&#xff0c;可以缓存发送信息&#xff1b;生产者向其中…

K8S网络插件故障处理

1网络插件故障 1此故障问题处理方法 查询ip是否正常是否是主节点IP地址如果不是需要更改 更改方式 1 修改calico.yaml文件的相应参数 # Cluster type to identify the deployment type - name: IP_AUTODETECTION_METHOD #增加内容value: "interfaceens*" 或者 value…

【论文速看】DL最新进展20241109-图像超分、物理信息神经网络、扩散模型

目录 【图像超分】【物理信息神经网络】【扩散模型】 【图像超分】 [2024 红外图像超分] Infrared Image Super-Resolution via Lightweight Information Split Network 论文链接&#xff1a;https://arxiv.org/pdf/2405.10561v2 代码链接&#xff1a;无 单图像超分辨率&…

Python学习从0到1 day26 第三阶段 Spark ① 数据输入

要学会 剥落旧痂 然后 循此新生 —— 24.11.8 一、Spark是什么 定义&#xff1a; Apache Spark 是用于大规模数据处理的统一分析引擎 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群&#xff0c;计算TB、PB乃至EB级别的海量数据…

[Python学习日记-63] 继承与派生

[Python学习日记-63] 继承与派生 简介 继承 派生 简介 上一篇文章我们学习了类如何使用&#xff0c;以及相关特性&#xff0c;也做了相关的练习&#xff0c;在练习当中发现类与类之间有时也会存在重复代码&#xff0c;其实在类中我们还有一个继承和派生的概念没有说&#xf…

基于 Encoder-only 架构的大语言模型

基于 Encoder-only 架构的大语言模型 Encoder-only 架构 Encoder-only 架构凭借着其独特的双向编码模型在自然语言处理任务中表现出色&#xff0c;尤其是在各类需要深入理解输入文本的任务中。 核心特点&#xff1a;双向编码模型&#xff0c;能够捕捉全面的上下文信息。 En…

Python学习------第四天

Python的判断语句 一、布尔类型和比较运算符 二、 if语句的基本格式 if语句注意空格缩进&#xff01;&#xff01;&#xff01; if else python判断语句的嵌套用法&#xff1a;

uniapp实现H5和微信小程序获取当前位置(腾讯地图)

之前的一个老项目&#xff0c;使用 uniapp 的 uni.getLocation 发现H5端定位不准确&#xff0c;比如余杭区会定位到临平区&#xff0c;根据官方文档初步判断是项目的uniapp的版本太低。 我选择的方式不是区更新uniapp的版本&#xff0c;是直接使用高德地图的api获取定位。 1.首…

测试网空投进行中 — 全面了解 DePIN 赛道潜力项目 ICN Protocol 及其不可错过的早期红利

随着云计算技术的飞速发展&#xff0c;越来越多的企业和个人对云服务的需求变得多样化且复杂化。然而&#xff0c;传统的中心化云服务平台&#xff08;如AWS、微软Azure等&#xff09;往往存在着高成本、数据隐私保护不足以及灵活性差等问题。 为了解决这些挑战&#xff0c;Imp…

IntelliJ IDEA 使用心得与常用快捷键

刚开始学习写Java的时候&#xff0c;用的eclipse&#xff0c;正式工作后&#xff0c;主要用的myeclipse&#xff0c;去年初在前辈的推荐下&#xff0c;在2折的时候买了正版的 IntelliJ IDEA 和 Pycharm&#xff0c;12.0版终生使用&#xff0c;一年更新。 使用前早就久闻其名&am…

【rust】rust基础代码案例

文章目录 代码篇HelloWorld斐波那契数列计算表达式&#xff08;加减乘除&#xff09;web接口 优化篇target/目录占用一个g&#xff0c;仅仅一个actix的helloWorld demo升级rust版本&#xff0c; 通过rustupcargo换源windows下放弃吧&#xff0c;需要额外安装1g的toolchain并且要…

施工企业为什么要用工程项目管理软件?工程项目管理软件的用处是什么?

施工企业一定会遇到哪些问题&#xff1f;工人怠工、材料浪费、数据造假、工期拖延、质量问题、安全隐患等。这些问题正在悄然侵蚀建施工业的经济效益。每一个环节的失控都可能导致巨大的经济损失&#xff0c;还可能损害企业的声誉。面对日益复杂的工程管理环境&#xff0c;如何…

【C++】详解RAII思想与智能指针

&#x1f308; 个人主页&#xff1a;谁在夜里看海. &#x1f525; 个人专栏&#xff1a;《C系列》《Linux系列》 ⛰️ 丢掉幻想&#xff0c;准备斗争 目录 引言 内存泄漏 内存泄漏的危害 内存泄漏的处理 一、RAII思想 二、智能指针 1.auto_ptr 实现原理 模拟实现 弊端…

所谓的情商高,其实就是会说话!

所谓的情商高&#xff0c;其实就是会说话&#xff01; 1.当遇到不知道的事情时&#xff0c;不要直截了当地说“不知道”。而应委婉地表达为“我想听听你的看法”。 如此既能避免尴尬&#xff0c;又能展现出对对方见解的尊重和期待。 2.不要简单地说“我迟到了”&#xff0c;…

ALB搭建

ALB: 多级分发、消除单点故障提升应用系统的可用性&#xff08;健康检查&#xff09;。 海量微服务间的高效API通信。 自带DDoS防护&#xff0c;集成Web应用防火墙 配置&#xff1a; 1.创建ECS实例 2.搭建应用 此处安装的LNMP 3.创建应用型负载均衡ALB实例 需要创建服务关联角…

【spark面试】spark的shuffle过程

概述 所有的shuffle的过程本质上就是一个task将内存中的数据写入磁盘&#xff0c;然后另一个task将磁盘中的数据读入内存的过程。 对于mapreduce来说&#xff0c;我们将内存中的数据写入磁盘成为maptask&#xff0c;将磁盘中的数据读入内存称为reducetask。 而对于spark来说&…

Android 实现一个系统级的悬浮秒表

前言 由于项目需要将手机录屏和时间日志对应起来&#xff0c;一般的手机录屏只能看到分钟&#xff0c;但是APP的日志输出通常都是秒级别的&#xff0c;于是决定自己手撸一个悬浮秒表&#xff08;有拖拽效果&#xff09;。 效果如下 具体实现 大致的实现思路&#xff1a; 创…

【科普小白】LLM大语言模型的基本原理

一、要了解LLM大模型的基本原理就要先来了解一下自然语言处理&#xff08;NLP&#xff09;。 NLP 是 AI 的一个子领域&#xff0c;专注于使计算机能够处理、解释和生成人类语言&#xff0c;主要任务包括&#xff1a;文本分类、自动翻译、问题回答、生成文本等。到底是NLP促生了…

Go语言开发商城管理后台-GoFly框架商城插件已发布 需要Go开发商城的朋友可以来看看哦!

温馨提示&#xff1a;我们分享的文章是给需要的人&#xff0c;不需要的人请绕过&#xff0c;文明浏览&#xff0c;误恶语伤人&#xff01; 前言 虽然现在做商城的需求不多&#xff0c;但有很多项目中带有商城功能&#xff0c;如社区医院系统有上服务套餐、理疗产品需求、宠物…

ts 如何配置引入 json 文件

ts 如何配置引入 json 文件 参考文档&#xff1a; https://maxgadget.dev/article/how-to-import-a-json-file-in-typescript-a-comprehensive-guide 项目中有一个 .json 的文件是配置文件&#xff0c;如何引入到 ts 项目中 配置 tsconfig.json 文件&#xff0c;添加这两个 {…