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

Halcon HImage 与 Qt QImage 的相互转换(修订版)

很久以前,我写过一遍文章来介绍 HImage 和 QImage 之间的转换方法。(https://blog.csdn.net/liyuanbhu/article/details/91356988)

这个代码其实是有些问题的。因为我们知道 QImage 中的图像数据不一定是连续的,尤其是图像的宽度是奇数时,每行数据后面基本都会多填充几个字节将每行的字节数凑成4的整倍数。

HImage 内部如何存储我不是很确定。但是GenImage1() 函数,GenImage3() 函数和 GenImageInterleaved() 函数里面输入图像数据都要求是连续的。因此,如果不判断QImage 的数据是否连续,直接将图像数据传过来有可能获得的图像是错误的。

本来我懒得写这篇博客。但是这么多年过去了。在网上搜相关的代码,竟然还是没有一个代码是正确考虑这个问题的。中文互联网上技术博客水平之低真是令人瞠目。

所以我还是写一写这个问题,避免大家重复的遇到这个 bug 吧。

首先是将 QImage 转换为 HImage 的代码。与原来的代码相比,就是在每种图像类型转换时增加了个判断。如果QImage 图像数据不是连续的,那么就一行一行的拷贝数据。

#include "himageqimage.h"
#include <QDebug>
using namespace HalconCpp;/*** @brief QImage2HImage 将 Qt QImage 转换为 Halcon 的 HImage* @param from 输入的 QImage* @param to 输出的 HImage ,from 和 to 不共享内存数据。 每次都会为 to 重新分配内存。* @return true 表示转换成功,false 表示转换失败。*/
bool QImage2HImage(QImage &from, HalconCpp::HImage &to)
{if(from.isNull()) return false;int width = from.width(), height = from.height();QImage::Format format = from.format();if(format == QImage::Format_RGB32 ||format == QImage::Format_ARGB32 ||format == QImage::Format_ARGB32_Premultiplied){if(from.bytesPerLine() == 4 * width){to.GenImageInterleaved(from.bits(), "bgrx", width, height, 0,  "byte", width, height, 0, 0, 8, 0);}else{to.GenImageInterleaved(from.bits(), "bgrx", width, height, 0,  "byte", width, height, 0, 0, 8, 0);uchar *R, *G, *B;HString Type;Hlong Width, Height;to.GetImagePointer3(reinterpret_cast<void **>(&R),reinterpret_cast<void **>(&G),reinterpret_cast<void **>(&B), &Type, &Width, &Height);for(int row = 0; row < height; row ++){QRgb* line = reinterpret_cast<QRgb*>(from.scanLine(row));for(int col = 0; col < width; col ++){*R = qRed(line[col]);*G = qGreen(line[col]);*B = qBlue(line[col]);++R;++G;++B;}}}return true;}else if(format == QImage::Format_RGB888){if(from.bytesPerLine() == 3 * width){to.GenImageInterleaved(from.bits(), "rgb", width, height, 0,  "byte", width, height, 0, 0, 8, 0);}else{to.GenImageInterleaved(from.bits(), "rgb", width, height, 0,  "byte", width, height, 0, 0, 8, 0);uchar *R, *G, *B;HString Type;Hlong Width, Height;to.GetImagePointer3(reinterpret_cast<void **>(&R),reinterpret_cast<void **>(&G),reinterpret_cast<void **>(&B), &Type, &Width, &Height);for(int row = 0; row < height; row ++){unsigned char* line = reinterpret_cast<unsigned char *>(from.scanLine(row));for(int col = 0; col < width; col ++){*R ++ = *line ++;*G ++ = *line ++;*B ++ = *line ++;}}}return true;}else if(format == QImage::Format_Grayscale8 || format == QImage::Format_Indexed8){if(from.bytesPerLine() == width){to.GenImage1("byte", width, height, from.bits());}else// 这时说明每行数据之间有填充字节。因此需要重新写数据{to.GenImageConst("byte", width, height);Hlong W, H; HString Type;unsigned char * pTo = reinterpret_cast<unsigned char *>( to.GetImagePointer1(&Type, &W, &H) );for(int row = 1; row < H; row ++){const unsigned char * pSrc = from.constScanLine(row);unsigned char * pDist = pTo + row * W;memcpy( pDist, pSrc, static_cast<size_t>(W));}}return true;}return false;
}

下面是 HImage 转 QImage。基本原理也是相同的。拷贝数据之前判断一下QImage 数据是否连续。不连续就一行一行的处理。

/*** @brief HImage2QImage 将 Halcon 的 HImage 转换为 Qt 的 QImage* @param from HImage ,暂时只支持 8bits 灰度图像和 8bits 的 3 通道彩色图像* @param to QImage ,这里 from 和 to 不共享内存。如果 to 的内存大小合适,那么就不用重新分配内存。所以可以加快速度。* @return  true 表示转换成功,false 表示转换失败*/
bool HImage2QImage(HalconCpp::HImage &from, QImage &to)
{Hlong width;Hlong height;from.GetImageSize(&width, &height);HTuple channels = from.CountChannels();HTuple type = from.GetImageType();if( strcmp(type[0].S(), "byte" )) // 如果不是 byte 类型,则失败{return false;}QImage::Format format;switch(channels[0].I()){case 1:format = QImage::Format_Grayscale8;break;case 3:format = QImage::Format_RGB888;break;default:return false;}if(to.width() != width || to.height() != height || to.format() != format){to = QImage(static_cast<int>(width),static_cast<int>(height),format);}HString Type;if(channels[0].I() == 1){unsigned char * pSrc = reinterpret_cast<unsigned char *>( from.GetImagePointer1(&Type, &width, &height) );if(to.bytesPerLine() == width){memcpy( to.bits(), pSrc, static_cast<size_t>(width) * static_cast<size_t>(height) );}else{for(int row = 1; row < height; row ++){unsigned char * pDistLine = to.scanLine(row);const unsigned char * pSrcLine = pSrc + row * width;memcpy( pDistLine, pSrcLine, static_cast<size_t>(width));}}return true;}else if(channels[0].I() == 3){uchar *R, *G, *B;from.GetImagePointer3(reinterpret_cast<void **>(&R),reinterpret_cast<void **>(&G),reinterpret_cast<void **>(&B), &Type, &width, &height);for(int row = 0; row < height; row ++){unsigned char * line = reinterpret_cast<unsigned char *>(to.scanLine(row));for(int col = 0; col < width; col ++){*line++ = *R++;*line++ = *G++;*line++ = *B++;}}return true;}return false;
}

相关文章:

Halcon HImage 与 Qt QImage 的相互转换(修订版)

很久以前&#xff0c;我写过一遍文章来介绍 HImage 和 QImage 之间的转换方法。&#xff08;https://blog.csdn.net/liyuanbhu/article/details/91356988&#xff09; 这个代码其实是有些问题的。因为我们知道 QImage 中的图像数据不一定是连续的&#xff0c;尤其是图像的宽度…...

【Golang】——Gin 框架中的模板渲染详解

Gin 框架支持动态网页开发&#xff0c;能够通过模板渲染结合数据生成动态页面。在这篇文章中&#xff0c;我们将一步步学习如何在 Gin 框架中配置模板、渲染动态数据&#xff0c;并结合静态资源文件创建一个功能完整的动态网站。 文章目录 1. 什么是模板渲染&#xff1f;1.1 概…...

CSS:导航栏三角箭头

用CSS实现导航流程图的样式。可根据自己的需求进行修改&#xff0c;代码精略的写了一下。 注&#xff1a;场景一和场景二在分辨率比较低的情况下会有一个1px的缝隙不太优雅&#xff0c;自行处理。有个方法是直接在每个外面包一个DIV&#xff0c;用动态样式设置底色。 场景一、…...

onlyoffice Command service(命令服务)使用示例

一、说明 文档在这里&#xff1a;https://api.onlyoffice.com/docs/docs-api/additional-api/command-service/ 命令服务提供有几个简单的接口封装。也提供了前端和后端同时操作文档的可能。 二、正文 命令服务地址&#xff1a;https://documentserver/coauthoring/Com…...

QSS 设置bug

问题描述&#xff1a; 在QWidget上add 一个QLabel&#xff0c;但是死活不生效 原因&#xff1a; c 主程序如下&#xff1a; QWidget* LOGO new QWidget(logo_wnd);LOGO->setFixedSize(logo_width, 41);LOGO->setObjectName("TittltLogo");QVBoxLayout* tit…...

交换排序——快速排序

交换排序——快速排序 7.7 交换排序——快速排序快速排序概念c语言的库函数qsort快速排序框架quickSort 7.7 交换排序——快速排序 快速排序概念 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff08;下文简称快排&#xff09;&#xff0c;其基本思想为&a…...

nodejs入门(1):nodejs的前后端分离

一、引言 我关注nodejs还是从前几年做了的一个电力大数据展示系统开始的&#xff0c;当然&#xff0c;我肯定是很多年的计算机基础的&#xff0c;万变不离其宗。 现在web网站都流行所谓的前后端结构&#xff0c;不知不觉我也开始受到这个影响&#xff0c;以前都是前端直接操作…...

笔记|M芯片MAC (arm64) docker上使用 export / import / commit 构建amd64镜像

很简单的起因&#xff0c;我的东西最终需要跑在amd64上&#xff0c;但是因为mac的架构师arm64&#xff0c;所以直接构建好的代码是没办法跨平台运行的。直接在arm64上pull下来的docker镜像也都是arm64架构。 检查镜像架构&#xff1a; docker inspect 8135f475e221 | grep Arc…...

gorm框架

连接 需要下载mysql的驱动 go get gorm.io/driver/mysql go get gorm.io/gorm 约定 主键&#xff1a;GORM 使用一个名为ID 的字段作为每个模型的默认主键。表名&#xff1a;默认情况下&#xff0c;GORM 将结构体名称转换为 snake_case 并为表名加上复数形式。 例如&#xf…...

免费送源码:Java+Springboot+MySQL Springboot多租户博客网站的设计 计算机毕业设计原创定制

Springboot多租户博客网站的设计 摘 要 博客网站是当今网络的热点&#xff0c;博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体&#xff0c;Blog站点所形成的网状结构促成了不同于以往社区的Blog文化&#xff0c;Blog技术缔造了“博客”文化。本文课题研究的“…...

【ASR技术】WhisperX安装使用

介绍 WhisperX 是一个开源的自动语音识别&#xff08;ASR&#xff09;项目&#xff0c;由 m-bain 开发。该项目基于 OpenAI 的 Whisper 模型&#xff0c;通过引入批量推理、强制音素对齐和语音活动检测等技术。提供快速自动语音识别&#xff08;large-v2 为 70 倍实时&#xf…...

【计算机网络】协议定制

一、结构化数据传输流程 这里涉及协议定制、序列化/反序列化的知识 对于序列化和反序列化&#xff0c;有现成的解决方案&#xff1a;①json ②probuff ③xml 二、理解发送接收函数 我们调用的所有发送/接收函数&#xff0c;根本就不是把数据发送到网络中&#xff01;本质都是…...

【SQL】mysql常用命令

为方便查询&#xff0c;特整理MySQL常用命令。 约定&#xff1a;$后为Shell环境命令&#xff0c;>后为MySQL命令。 1 常用命令 第一步&#xff0c;连接数据库。 $ mysql -u root -p # 进入MySQL bin目录后执行&#xff0c;回车后输入密码连接。# 常用参数&…...

阿里云引领智算集群网络架构的新一轮变革

阿里云引领智算集群网络架构的新一轮变革 云布道师 11 月 8 日~ 10 日在江苏张家港召开的 CCF ChinaNet&#xff08;即中国网络大会&#xff09;上&#xff0c;众多院士、教授和业界技术领袖齐聚一堂&#xff0c;畅谈网络未来的发展方向&#xff0c;聚焦智算集群网络的创新变…...

几何合理的分片段感知的3D分子生成 FragGen - 评测

FragGen 来源于 2024 年 3 月 25 日 预印本的文章&#xff0c;文章题目是 Deep Geometry Handling and Fragment-wise Molecular 3D Graph Generation&#xff0c; 作者是 Odin Zhang&#xff0c;侯廷军&#xff0c;浙江大学药学院。FragGen 是一个基于分子片段的 3D 分子生成模…...

Python爬虫下载新闻,Flask展现新闻(2)

上篇讲了用Python从新闻网站上下载新闻&#xff0c;本篇讲用Flask展现新闻。关于Flask安装网上好多教程&#xff0c;不赘述。下面主要讲 HTML-Flask-数据 的关系。 简洁版 如图&#xff0c;页面简单&#xff0c;主要显示新闻标题。 分页&#xff0c;使用最简单的分页技术&…...

监控易监测对象及指标之:全面监控华为FusionInsight服务

随着大数据技术的广泛应用&#xff0c;华为FusionInsight以其卓越的性能和稳定性&#xff0c;成为了众多企业处理和分析海量数据的首选平台。然而&#xff0c;为了确保FusionInsight服务的持续稳定运行&#xff0c;对其进行全面监控至关重要。本文基于监控易工具&#xff0c;对…...

SQL面试题——蚂蚁SQL面试题 会话分组问题

会话分组问题 这里的分组不是简单的分组,而是会话的分组。 比如说,进入一个网站以后,可以连续的点击很多个页面,后台会记录用户的行为日志; 如果T日上午连续点击几个页面后退出了网站,直到第二天的下午才再次进入网站,单单从时间线上来看,昨天退出的那条日志跟今天进…...

nfs服务器--RHCE

一&#xff0c;简介 NFS&#xff08;Network File System&#xff0c;网络文件系统&#xff09;是FreeBSD支持的文件系统中的一种&#xff0c;它允许网络中的计 算机&#xff08;不同的计算机、不同的操作系统&#xff09;之间通过TCP/IP网络共享资源&#xff0c;主要在unix系…...

React--》如何高效管理前端环境变量:开发与生产环境配置详解

在前端开发中&#xff0c;如何让项目在不同环境下表现得更为灵活与高效&#xff0c;是每个开发者必须面对的挑战&#xff0c;从开发阶段的调试到生产环境的优化&#xff0c;环境变量配置无疑是其中的关键。 env配置文件&#xff1a;通常用于管理项目的环境变量&#xff0c;环境…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践&#xff0c;很多人以为AI已经强大到不需要程序员了&#xff0c;其实不是&#xff0c;AI更加需要程序员&#xff0c;普通人…...

智能体革命:企业如何构建自主决策的AI代理?

OpenAI智能代理构建实用指南详解 随着大型语言模型&#xff08;LLM&#xff09;在推理、多模态理解和工具调用能力上的进步&#xff0c;智能代理&#xff08;Agents&#xff09;成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同&#xff0c;智能代理能够自主执行工…...

ABAP设计模式之---“Tell, Don’t Ask原则”

“Tell, Don’t Ask”是一种重要的面向对象编程设计原则&#xff0c;它强调的是对象之间如何有效地交流和协作。 1. 什么是 Tell, Don’t Ask 原则&#xff1f; 这个原则的核心思想是&#xff1a; “告诉一个对象该做什么&#xff0c;而不是询问一个对象的状态再对它作出决策。…...