Kithara和Halcon (二)

Kithara使用Halcon + QT 进行二维码实时识别


目录

    • Kithara使用Halcon + QT 进行二维码实时识别
      • Halcon 简介以及二维码检测的简要说明
          • Halcon 简介
          • Halcon的二维码检测功能
      • Qt应用框架简介
      • 项目说明
      • 关键代码
      • 抖动测试
          • 测试平台:
          • 测试结果:
      • 开源源码


Halcon 简介以及二维码检测的简要说明

Halcon 简介

Halcon 是一款由德国MVTec Software GmbH开发的机器视觉软件包,它为工业自动化提供了强大的图像分析和处理工具。Halcon 软件广泛应用于质量控制、定位、测量、识别和引导机器人等场景,其核心优势在于高性能的图像处理算法、丰富的功能库以及跨平台的兼容性。

Halcon 提供了基于C++和.NET的API,支持Windows、Linux和macOS操作系统,并且能够集成到各种开发环境中,如Visual Studio、Eclipse等。它不仅适用于PC环境,还支持嵌入式系统,使得Halcon成为工业4.0和物联网(IoT)应用的理想选择。

Halcon的二维码检测功能

二维码检测是Halcon中一个重要的应用领域,尤其在物流、制造业和零售业中,二维码的快速准确读取对于追踪和管理物品至关重要。Halcon提供了专门的工具和算子来高效地检测和解码二维码。

常见的二维码检测流程

  • 创建二维码阅读器模板
    使用create_data_code_2d_model算子初始化一个二维码检测模型。这一步会根据预期的二维码类型和环境条件设定初始参数。

  • 设置二维码阅读器参数
    通过set_data_code_2d_param算子调整二维码检测模型的参数。这些参数可能包括二维码的大小范围、旋转角度、噪声容忍度等,以适应不同的应用场景。

  • 检测和读取二维码
    应用find_data_code_2d算子在输入图像中查找二维码。此算子会返回二维码的位置和方向信息。

  • 解码二维码
    read_data_code_2d算子用于从检测到的二维码中提取编码信息。这一步骤将二维码转换为可读的文本或数据。

  • 结果后处理
    解码后的数据通常需要进一步处理,比如验证、存储或发送给其他系统。

  • 二维码检测的关键点
    图像预处理:在检测之前,可能需要对图像进行预处理,例如去噪、增强对比度或校正图像失真,以提高检测的准确性。
    参数调整:适当的参数设置对于提高二维码检测的速度和可靠性至关重要。这可能需要根据具体的应用场景和环境条件进行实验和优化。
    多二维码识别:在复杂场景中,可能需要同时检测多个二维码。Halcon的算子支持这一需求,能够处理密集或重叠的二维码。

总之,Halcon的二维码检测功能结合了先进的图像处理技术和直观的编程接口,使得用户能够在各种工业环境中实现高精度和高效率的二维码识别。

关于 Halcon在Kithara中使用可以查阅此文章Kithara中使用Halcon (一),更多关于学习Halcon的方法可以去 Halcon官网关于二维码检测的介绍。

Qt应用框架简介

  • Qt 应用框架简介
    Qt 是一个跨平台的C++图形用户界面应用程序开发框架,由挪威公司 Trolltech(现为 The Qt Company)于1991年开发。Qt 不仅支持 Windows、Linux 和 macOS 等桌面操作系统,还支持 Android、iOS 等移动平台,甚至可以用于嵌入式系统开发,如 QNX 和 Linux for Devices。

核心特性

  • 跨平台性:Qt 最显著的特点就是其强大的跨平台能力,允许开发者编写一次代码即可在多个平台上运行,极大地提高了开发效率和降低了维护成本。

  • GUI 构建:Qt 提供了一套丰富的组件库,包括按钮、列表、表格、对话框等,用于构建美观且功能完备的用户界面。此外,Qt Creator 集成开发环境中的设计器工具允许开发者通过拖放方式构建界面。

  • 信号与槽机制:这是 Qt 中一种独特的事件处理机制,用于对象之间的通信。信号(Signal)是在对象中定义的,当特定事件发生时被自动触发;槽(Slot)则是可以响应信号的函数。这种机制简化了事件驱动程序的编写。

  • 国际化与本地化:Qt 支持多语言界面,可以轻松地为应用程序添加多种语言支持,满足全球用户的需求。

  • 网络功能:Qt 内置了对网络编程的支持,包括 HTTP、FTP、TCP/IP、UDP 等协议,使得开发网络应用变得简单。
    数据库集成:Qt 提供了数据库访问模块,支持 SQLite、MySQL、PostgreSQL 等多种数据库,便于开发数据驱动的应用。

  • 多媒体支持:通过 QtMultimedia 模块,开发者可以轻松地在应用中集成音频和视频功能。

  • 性能优化:Qt 提供了多种工具和技术,如 QML 和 OpenGL,用于构建高性能的图形界面和动画效果。

开发工具
Qt Creator:官方提供的集成开发环境,集成了代码编辑器、调试器、项目管理工具和 UI 设计器,大大提高了开发效率。
Qt Designer:一个用于设计和编辑用户界面的工具,支持拖放操作,可以生成 Qt 的 UI 代码。
Qt Assistant:一个帮助文档浏览器,包含了 Qt 的所有 API 文档和教程,是学习 Qt 的重要资源。

社区与支持
Qt 拥有庞大的开发者社区,提供了丰富的资源、示例代码和第三方库。无论是初学者还是经验丰富的开发者,都能在社区中找到所需的支持和解决方案。
总之,Qt 是一个功能全面、易于使用的开发框架,特别适合那些希望快速开发高质量跨平台应用的开发者。无论是桌面应用、移动应用还是嵌入式设备上的应用,Qt 都能提供强大的支持。

项目说明

使用Kithara Windows实时套件和Haclon的组合,可以进行二维码检测,并结合Qt图形化应用框架实时显示检测图像,实现选择不同网口的摄像头并实时调节检测圆的参数,监控测试抖动。

编写流程:

  1. 导入Kithara Windows实时套件和Halcon库。
  2. 使用Qt图形化应用框架创建一个界面,包括一个图像显示区域和解析数据展示。
  3. 初始化Kithara并打开摄像头,开始实时获取图像。
  4. 在任务处理中,将实时获取的图像传递给Halcon任务进行二维码检测。
  5. 根据检测结果,在图像上绘制二维码加检测区域,并通过共享内存将数据回传到应用层将图像实时显示在界面的图像显示区域中以及显示检测结果。
  6. 可以添加抖动检测功能,进行抖动测试。
  7. 结束时,释放资源和关闭摄像头。

在这里插入图片描述
在这里插入图片描述

关键代码


// 创建Halcon对象
HObject CreateImage(const uint type, const Hlong width, const Hlong height, void* data)
{KS_printK("CreateImage");HObject ho_image;switch (type){case KS_CAMERA_PIXEL_MONO_8:{const HImage image("byte", width, height, data);ho_image = image;break;}case KS_CAMERA_PIXEL_RGB_8:{HImage image;image.GenImageInterleaved(data, "rgb", width, height, 0,  "byte", width, height, 0, 0, 8, 0);Rgb1ToGray(image,&ho_image);break;}default:break;}return ho_image;
}// 识别二维码
HTuple QCoderCheck(const HTuple& hv_data_code_handle,const HObject& ho_image, SharedData *krenel_data_ptr)
{HObject ho_symbol_xl_ds;HTuple hv_result_handles;HTuple hv_decoded_data_strings;HTuple hv_row{}, hv_col{};//“二维码”运算符将句柄返回给二维数据代码模型,可用于所有进一步的用途对数据代码的操作。FindDataCode2d(ho_image, &ho_symbol_xl_ds, hv_data_code_handle, HTuple(), HTuple(), &hv_result_handles, &hv_decoded_data_strings);GetContourXld(ho_symbol_xl_ds, &hv_row, &hv_col);if ( hv_row.Length() <= QCODE_XLD_SIZE){for (int i = 0; i < hv_row.Length(); i++){const double xld_row = hv_row.ToDArr()[i];const double xld_col = hv_col.ToDArr()[i];krenel_data_ptr->check_qcode_param.qcode_xld_row[i] = xld_row;krenel_data_ptr->check_qcode_param.qcode_xld_col[i] = xld_col;}}return  hv_decoded_data_strings;
}// 这是实时任务将运行的函数,并对接收到的图像执行 Halcon 操作。只有实时任务才应调用 Halcon 函数。
KSError __stdcall HalconCallback(void * /*pArgs*/, void * /*pContext*/)
{KS_printK("HalconCallback called!\n");// 表示已准备好处理图像。krenel_data_ptr_->ready = 1;// 图形抖动性测试int64 last_diff_time {0};int is_valid_time = 0;  // 时间是否有效 0 无效 1 时间有效int count = 0;  // 计数器int64 jitter_time_sum {0};  // 抖动总时间// 设置halcon编码格式//SetSystem("filename_encoding", "utf8");HTuple hv_data_code_handle;CreateDataCode2dModel("QR Code", HTuple(), HTuple(), &hv_data_code_handle);//SetDataCode2dParam (hv_data_code_handle, "string_encoding", "utf8");// 处理循环,此循环仅在发出中止信号时停止。for (;;){// 等待图像接收或停止的通知。KSError error = KS_waitForEvent(krenel_data_ptr_->image_received_event_handle, KSF_NO_FLAGS, 0);if (error != KS_OK) { KS_printK("KS_waitForEvent failed! \n"); }if (krenel_data_ptr_->abort != 0) { break; }// 计数器count++;// 获取当前时间,用于计算图像处理的抖动时间int64 last_time {0};error = KS_getClock(&last_time, KS_CLOCK_MEASURE_HIGHEST);if (error != KS_OK) { return error; }// 获取接收到的图像数据的缓冲区KSCameraBlock *camera_block;void *image_data;error = KS_recvCameraImage(krenel_data_ptr_->stream_handle, &image_data, &camera_block,KSF_NO_FLAGS);if (error != KS_OK){krenel_data_ptr_->ready = 1;continue;}//如果接收到的块类型不是图像,我们跳过。在任何情况下,如果 KS_recvCameraImage() 成功接收到的缓冲区必须使用 KS_releaseCameraImage() 释放。if (camera_block->blockType != KS_CAMERA_BLOCKTYPE_IMAGE){KS_releaseCameraImage(krenel_data_ptr_->stream_handle, image_data, KSF_NO_FLAGS);break;}// 在构建图形之前,请检查接收到的图像是否具有正确的像素格式。const auto *image_block = reinterpret_cast<KSCameraImage *>(camera_block);// 现在,我们将GigE Vision图像转换为Halcon图像。有几种方法可以实现此目的。// 请参阅 Halcon 文档,了解从指针到像素创建图像的正确函数数据。// 这里我们使用 HImage 类的构造函数之一,这等于调用运算符 gen_image1。// 它将复制像素数据。尽管如此,像素的格式必须得到 Halcon 的支持,// 否则,必须执行转换。// 二维码识别HObject ho_image = CreateImage(image_block->pixelFormat, image_block->width, image_block->height, image_data);HTuple ret = QCoderCheck(hv_data_code_handle, ho_image, krenel_data_ptr_);const char *ret_char = ret.ToString();if (const size_t ret_size = ret.ToString().Length(); ret_size < QCODE_VALUE_SIZE - 1){KSRTL_strncpy(krenel_data_ptr_->check_qcode_param.qcode_value, ret_char, QCODE_VALUE_SIZE);}else{KSRTL_strncpy(krenel_data_ptr_->check_qcode_param.qcode_value, "", QCODE_VALUE_SIZE);}// 填充图像信息到共享内存中krenel_data_ptr_->image_info.image_height = image_block->height;krenel_data_ptr_->image_info.image_width = image_block->width;krenel_data_ptr_->image_info.pixel_format = image_block->pixelFormat;if (image_block->pixelFormat == KS_CAMERA_PIXEL_MONO_8){KS_memCpy(pixel_buffer_, image_data, image_block->width * image_block->height, KSF_NO_FLAGS);}else if (image_block->pixelFormat == KS_CAMERA_PIXEL_BGR_8 || image_block->pixelFormat == KS_CAMERA_PIXEL_RGB_8){KS_memCpy(pixel_buffer_, image_data,  image_block->width * image_block->height * 3, KSF_NO_FLAGS);}// 释放图像数据error = KS_releaseCameraImage(krenel_data_ptr_->stream_handle, image_data, KSF_NO_FLAGS);if (error != KS_OK) { KS_printK("KS_releaseCameraImage failed! \n"); }//  图形处理完成后,减去上次处理完成的时间int64 time {0};error = KS_getClock(&time, KS_CLOCK_MEASURE_HIGHEST);if (error != KS_OK) { return error; }// 检测圆处理时间const int64 diff_time = time - last_time;int64 time_cyc = diff_time;KS_convertClock(&time_cyc, KS_CLOCK_MEASURE_HIGHEST, KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);krenel_data_ptr_->jitter_value.time_cyc = time_cyc;if (is_valid_time == 0){last_diff_time = diff_time;is_valid_time = 1;}else{// 处理时间的抖动const int64 jitter_time = diff_time - last_diff_time;int64 single_time = jitter_time;KS_convertClock(&single_time, KS_CLOCK_MEASURE_HIGHEST, KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS); // 100 ns 为单位last_diff_time = diff_time;jitter_time_sum += single_time;if (krenel_data_ptr_->jitter_value.lat_min > single_time){krenel_data_ptr_->jitter_value.lat_min = single_time;}if (krenel_data_ptr_->jitter_value.lat_max < single_time){krenel_data_ptr_->jitter_value.lat_max = single_time;}krenel_data_ptr_->jitter_value.lat_avg = jitter_time_sum / count;krenel_data_ptr_->jitter_value.cur_val = single_time;}krenel_data_ptr_->ready = 1;}return KS_OK;
}

抖动测试

测试平台:

在这里插入图片描述

测试结果:
  • CPU GPU空载测试
    在这里插入图片描述
    在这里插入图片描述

  • CPU满载运行,GPU空载运行
    在这里插入图片描述

  • CPU满载运行,GPU满载运行
    在这里插入图片描述

  • CPU空载运行,GPU满载运行
    在这里插入图片描述

Kithara Windows实时套件得益于其CPU独占技术,即使在Windows cpu负载较高的情况下,也能够稳定地处理Haclon对图像中二维码的检测任务并输出结果,但是GPU负载对图像处理响应较大,在实际项目中应避免GPU存在过高负载。 这种稳定性确保了在各种工作负载下,检测任务都能保持一致的性能表现。此外,我们还对不同平台对检测任务的影响进行了测试,进一步验证了Kithara Windows实时套件在多种环境中的优越性能。这些测试结果表明,无论平台和负载如何,该套件都能提供可靠、高效的图像处理能力。

在进行相同的检测任务时,我们发现抖动现象存在显著差异,这表明用于性能检测的CPU在图像处理方面具有一定的影响。此外,在测试过程中我们还注意到,不同的算法和图像的复杂度也会对结果产生影响。这些因素综合作用,揭示了在图像处理任务中,硬件和软件的选择对性能的最终表现有着重要的决定性作用。通过深入分析这些变量,我们可以更好地优化检测系统,从而提高整体的处理效率和准确性。

开源源码

测试源码现已开源,项目Demo均是测试代码,请勿用于实际项目!

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

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

相关文章

STM32CubeMX的介绍与简单使用

STM32CubeMX提供了一个直观的图形用户界面&#xff0c;允许用户通过简单的操作完成对STM32微控制器的配置&#xff0c;包括引脚分配、时钟配置、外设初始化等。专为STM32微控制器设计&#xff0c;旨在帮助开发者轻松配置和初始化STM32微控制器。用户可以通过拖拽和连接来配置芯…

关键词查找【Aho-Corasick 算法】

【全程干货】程序员必备算法&#xff01;AC自动机算法敏感词匹配算法&#xff01;动画演示讲解&#xff0c;看完轻松掌握&#xff0c;面试官都被你唬住&#xff01;&#xff01;_哔哩哔哩_bilibili 著名的多模匹配算法 引入依赖&#xff1a; <dependency><groupId>…

Vue3 Pinia/组件通信

2. pinaia 符合直觉的Vue.js状态管理库 集中式状态&#xff08;数据&#xff09;管理 官网 2.1 搭建pinaia环境 第一步&#xff1a;npm install pinia 第二步&#xff1a;操作src/main.ts import { createApp } from vue import App from ./App.vue/* 引入createPinia&…

Java面试八股之什么是声明式事务管理,spring怎么实现声明式事务管理?

什么是声明式事务管理&#xff0c;spring怎么实现声明式事务管理&#xff1f; 声明式事务管理是一种编程范式&#xff0c;它允许开发人员通过声明性的配置或注解&#xff0c;而不是硬编码事务处理逻辑&#xff0c;来指定哪些方法或类应该在其上下文中执行事务。这种方法将事务…

【PHP】系统的登录和注册

一、为什么要学习系统的登录和注册 系统的登录和注册可能存在多种漏洞&#xff0c;这些漏洞可能被恶意攻击者利用&#xff0c;从而对用户的安全和隐私构成威胁。通过学习系统的登录和注册理解整个登录和注册的逻辑方便后续更好站在开发的角度思考问题发现漏洞。以下是一些常见…

C++第二十七弹---优先级队列的高级应用:结合仿函数优化性能

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1 priority_queue的介绍和使用 1.1 priority_queue的介绍 1.2 priority_queue的使用 2 仿函数的介绍和使用 2.1 仿函数的介绍 2.2 仿函数的…

Python升级打怪—Django入门

目录 一、Django简介 二、安装Django 三、创建Dajngo项目 (一) 创建项目 (二) 项目结构介绍 (三) 运行项目 (四) 结果 一、Django简介 Django是一个高级Python web框架&#xff0c;鼓励快速开发和干净、实用的设计。由经验丰富的开发人员构建&#xff0c;它解决了web开…

【文件fd】文件描述符fd | 文件描述表

目录 1.文件描述符fd 2.系统调用的0/1/2 3.C语言的stdin/stdout/stderr 4.系统调用的0/1/2和C语言的stdin/stout/stderr二者的关系❓ 5.文件描述表 5.1 文件描述符概念 5.3 文件对象strcut file 5.4 进程和文件对应关系 5.5 文件描述符理解 5.6 源码查看 1.文件描述…

谷粒商城实战笔记-55-商品服务-API-三级分类-修改-拖拽数据收集

文章目录 一&#xff0c;拖拽后结点的parentCid的更新二&#xff0c;拖拽后结点的父节点下所有结点的sort排序属性的变化更新排序的逻辑代码分析 三&#xff0c;拖拽后结点及其子节点catLevel的变化判断是否需要更新 catLevel获取拖动后的新节点 更新 catLevel完整代码 这一节的…

mysql特殊字符、生僻字存储设置

mysql utf-8模式下&#xff0c;分为ut8mb3,utf8mb4&#xff0c;mb4是支持特殊字符、emoji表情的&#xff0c;mb3是不支持的。 报错信息&#xff1a; 1### Error updating database. Cause: java.sql.SQLException: Incorrect string value: \xF0\xA8\x92\x82\xE6\x95... fo…

MongoDB教程(二十):MongoDB正则表达式

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、正则表…

【ESP32 idf 硬件I2C驱动MPU6050获取六轴数值】

目录 I2C介绍配置安装驱动通信创建&删除命令链接容器起始时序写数据读数据结束时序开始命令 mpu6050 硬件i2c驱动代码&调试代码调试 I2C 介绍 介绍部分可以看我写的【ESP32 idf 软件模拟I2C驱动MPU6050实现六轴加速度的获取】&#xff0c;这个是使用软件模拟的I2C时序…

python在类中手动定义标准化输出函数

在深度学习等训练框架中&#xff0c;有时候需要对模型的名称、参数量、训练进度、中间结果等进行标准化输出&#xff0c;从而方便实时查看代码运行情况&#xff0c;这时&#xff0c;可以在类中手动定义如下标准化的输出函数&#xff0c;然后在需要输出的地方进行调用即可。 首…

鸿蒙北向开发 DevEco Studio 4.1 下载安装傻瓜式教程

开篇 由于鸿蒙处于快速发展中,鸿蒙的api快速迭代更新,老版本的DevEco studio无法支持更新版本的api,因此华为官网放弃了老版本的维护.直接从华为开发者官网无法下载老版本,当前华为开发者官网已经推出next版本了 DevEco studio3.1安装教程 上述教程提供的华为开发者官网地址已经…

linux怎么创建python

第一步&#xff0c;创建一个test文件夹。 第二步&#xff0c;打开终端进入该文件。 第三步&#xff0c;vim test.py。 第四步&#xff0c;编写代码。 第五步&#xff0c;编辑好之后&#xff0c;按Esc键切换到命令模式&#xff0c;然后输入:wq&#xff0c;再按回车键即可自动保存…

探索 SPL-404 协议标准:NFT 与 DeFi 的融合

在快速发展的数字资产领域中&#xff0c;NFT 协议标准持续演变&#xff0c;改变了我们对数字所有权和互动方式的理解。从 Art 到 Gamefi 等等&#xff0c;NFT 已经演变成数字经济的重要组成部分&#xff0c;吸引了广泛关注。遵循 ERC404 协议&#xff0c;SPL404 概念在 Solana …

AvaloniaUI的学习

相关网站 github:https://github.com/AvaloniaUI/Avalonia 官方中文文档&#xff1a;https://docs.avaloniaui.net/zh-Hans/docs/welcome IDE选择 VS2022VSCodeRider 以上三种我都尝试过&#xff0c;体验Rider最好。VS2022的提示功能不好&#xff0c;VSCode太慢&#xff0c…

flex/lex使用和学习

flex/lex用于生成解析配置文件的C代码&#xff0c;我们可以不用自己手动去做解析的工作&#xff0c;交由他们生成的代码去做。 假设&#xff0c;我有如下一个配置文件config.xml 配置文件中定义了三种channel,分别为SSIF, IPMB, NET&#xff0c;每一种channel都有4个int属性&a…

生成式AI:对话系统(Chat)与自主代理(Agent)的和谐共舞

生成式AI&#xff1a;对话与行动的和谐共舞 我们正站在一个令人激动的时代门槛上——生成式AI技术飞速发展&#xff0c;带来了无限的可能性。一个关键问题浮现&#xff1a;AI的未来是对话系统&#xff08;Chat&#xff09;的天下&#xff0c;还是自主代理&#xff08;Agent&am…

实时同步:使用 Canal 和 Kafka 解决 MySQL 与缓存的数据一致性问题

目录 1. 准备工作 2. 将需要缓存的数据存储 Redis 3. 监听 canal 存储在 Kafka Topic 中数据 1. 准备工作 1. 开启并配置MySQL的 BinLog&#xff08;MySQL 8.0 默认开启&#xff09; 修改配置&#xff1a;C:\ProgramData\MySQL\MySQL Server 8.0\my.ini log-bin"HELO…