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

【数据转换】- Halcon<->Mat

背景介绍

最近在写C#联合Haclon调用C++的.dll文件进行联合编程。大致需求就是C#设计界面,然后调用Haclon的图像处理库,C++把目标检测的模型进行TensorRT部署生成动态链接库,之后界面操作加载模型、对图像进行检测等功能。

设计界面如下,画面简陋,勿喷!!!
在这里插入图片描述

其中有步操作,我需要将Halcon的HImage格式转换成OpenCV的Mat 。很耗时!
测试一下
将一张大小为2448*2048的图像转成Mat,我最开始的想法是逐像素遍历并手动调整通道顺序(RGB → BGR) ,非常耗时,大概24524ms. 具体实现代码如下:

 // 获取Halcon图像的指针和数据
            HTuple pointerRed, pointerGreen, pointerBlue;
            HTuple type, width, height;

            // 获取图像大小
            HOperatorSet.GetImageSize(halconImage, out width, out height);

            // 对于彩色图像,分别获取每个通道的数据
            HOperatorSet.GetImagePointer3(halconImage, out pointerRed, out pointerGreen,
                                         out pointerBlue, out type, out width, out height);

            // 创建OpenCV的Mat对象 (3通道BGR格式)
            Mat cvImage = new Mat(height, width, MatType.CV_8UC3);
            
            // 将Halcon图像数据(RGB顺序)复制到OpenCV Mat中(BGR顺序)
            unsafe
            {
                byte* cvData = (byte*)cvImage.Data;
                byte* halconRed = (byte*)pointerRed.L;
                byte* halconGreen = (byte*)pointerGreen.L;
                byte* halconBlue = (byte*)pointerBlue.L;

                 创建计时器
                //Stopwatch stopwatch = new Stopwatch();

                 开始计时
                //stopwatch.Start();
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {

                        int index = y * width * 3 + x * 3;

                        // OpenCV使用BGR顺序,Halcon是RGB
                        cvData[index + 0] = halconBlue[y * width + x];   // B
                        cvData[index + 1] = halconGreen[y * width + x];  // G
                        cvData[index + 2] = halconRed[y * width + x];    // R

                    }
                }

耗时原因分析:

  1. 逐像素访问(最耗时)使用了 双重循环 for (y…) for (x…) 逐个像素处理,这种方式导致
    缓存不友好:内存访问不是连续的,导致 CPU 缓存命中率低。
    分支预测开销:循环内的条件判断(如 index 计算)会增加 CPU 流水线停顿。
    测试数据:对于 1920x1080 的图像,循环次数 = 2,073,600 次,每次循环还要计算 index。
  2. 指针计算复杂
  3. 通道顺序调整的冗余操作

开始优化

跟部门主管说了这个疑问,主管建议我使用MemoryCopy.
于是乎,升级之后版本,时间 30ms

try
            {
                // 检查输入图像是否有效
                if (himg == null || !himg.IsInitialized())
                {
                    throw new Exception("Halcon 图像未初始化或为空");
                }

                // 获取通道数
                HTuple htChannels = new HTuple();
                HOperatorSet.CountChannels(himg, out htChannels);

                if (htChannels.Length == 0)
                {
                    return null;
                }

                int channels = htChannels[0].I;
                HTuple width, height;
                HOperatorSet.GetImageSize(himg, out width, out height);

                // 检查图像尺寸是否有效
                if (width <= 0 || height <= 0)
                {
                    throw new Exception($"无效的图像尺寸: {width}x{height}");
                }

                Mat pImage;
                if (channels == 1) // 单通道(灰度)
                {
                    HTuple ptr, cType;
                    HOperatorSet.GetImagePointer1(himg, out ptr, out cType, out width, out height);

                    if (ptr.IP == IntPtr.Zero)
                    {
                        throw new Exception("Halcon 图像指针无效");
                    }

                    pImage = new Mat(height, width, MatType.CV_8UC1);
                    unsafe
                    {
                        Buffer.MemoryCopy((void*)ptr.IP, (void*)pImage.Data, width * height, width * height);
                    }

                }
                else if (channels == 3) // 三通道(RGB)
                {
                    HTuple ptrRed, ptrGreen, ptrBlue, cType;
                    HOperatorSet.GetImagePointer3(himg, out ptrRed, out ptrGreen, out ptrBlue, out cType, out width, out height);

                    if (ptrRed.IP == IntPtr.Zero || ptrGreen.IP == IntPtr.Zero || ptrBlue.IP == IntPtr.Zero)
                    {
                        throw new Exception("Halcon RGB 通道指针无效");
                    }

                    // 创建单通道 Mat 存储 R/G/B
                    using (Mat pImageRed = new Mat(height, width, MatType.CV_8UC1))
                    using (Mat pImageGreen = new Mat(height, width, MatType.CV_8UC1))
                    using (Mat pImageBlue = new Mat(height, width, MatType.CV_8UC1))
                    {
                        unsafe
                        {
                            Buffer.MemoryCopy((void*)ptrRed.IP, (void*)pImageRed.Data, width * height, width * height);
                            Buffer.MemoryCopy((void*)ptrGreen.IP, (void*)pImageGreen.Data, width * height, width * height);
                            Buffer.MemoryCopy((void*)ptrBlue.IP, (void*)pImageBlue.Data, width * height, width * height);
                        }

                        // 合并为 3 通道 RGB
                        pImage = new Mat();
                        Cv2.Merge(new[] { pImageBlue, pImageGreen, pImageRed }, pImage); // Halcon 默认顺序是 RGB,OpenCV 是 BGR
                    }
                }
                else
                {
                    throw new Exception($"不支持的通道数: {channels}(仅支持 1 或 3 通道)");
                }

                return pImage;
            }
            catch (Exception ex)
            {
                MessageBox.Show("转换失败", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

相关文章:

  • 为Windows10的WSL Ubuntu启动sshd服务并使用Trae远程连接
  • 软考网络工程师上午题
  • AndroidStudio无法识别连接夜神模拟器
  • Android开发:基于 Kotlin 协程的设备指令控制工具类设计与实现
  • Kong 可观测性最佳实践
  • 前端国际化-插件模式
  • Linux网站搭建(新手必看)
  • 项目启动报Error: cannot find module ‘node:path’
  • XXL-Job 处理大数据量并发任务的解决方案及底层原理
  • Java面试黄金宝典15
  • C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
  • 2、学习Docker前置操作
  • 深度学习框架PyTorch——从入门到精通(10)PyTorch张量简介
  • 第七章:优化热点语句_《C++性能优化指南》_notes
  • Day24:队列的最大值
  • 音视频新人如何快速上手nginx-rtmp-module
  • 人工智能之数学基础:瑞利商的推广形式——广义瑞利商
  • 如何排查C++程序的CPU占用过高的问题
  • Python爬虫:Feapder 的详细使用和案例
  • 在Ubuntu系统上安装连接服务器的图形化界面工具
  • 美乌矿产协议签署被曝“临门一脚”时生变,美方提附加条件
  • 中国强镇密码丨洪泽湖畔的蒋坝,如何打破古镇刻板印象
  • 过去24小时中美是否就关税问题进行过接触?外交部:没有
  • 国铁集团郑州局预计“五一”发送642.5万人
  • 智能终端出海服务创新联合体成立
  • 顺利撤离空间站,神十九乘组踏上回家之旅