当前位置: 首页 > 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;环境…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...