VisionPro软件Image Stitch拼接算法
2D图像拼接的3种情景
1.一只相机取像位置固定,或者多只相机固定位置拍图,硬拷贝拼图,采用CopyRegion工具实现
2.一只或多只相机在多个位置拍照,相机视野互相重叠,基于Patmax特征定位后,无缝
拼图;采用CogImageStitch类实现;
3.一只或多只相机在多个位置拍照,相机视野只有小范围重叠,或者不重叠,无法使用 Patmax特征定位,可以用标定板标定位置关系,使用CogImageStitch类实现拼图.
注意:此方法是是预先标定的位置关系,如果采用1只相机多个位置拍摄,需要机构保证重复运动的精度在允许范围内,否则可能造成图像错位。
注意:无论是哪种拼接方式,单相机或是多相机拍照,都需要尽量调节到同一个高度拍照,否则可能造成图像重影,模糊等问题;
1.CopyRegionTool硬拷贝拼图
1.请参考QuickBuild自带例程: Script_Stitch_Job.vpp
2.在CogJob的作业属性-取像脚本中实现多张图像拷 贝拼接
3.注意CopyRegion工具的属性, DesinationImageAlignmentX和Y用于指定子图像在拼接大图的位置偏移

2.基于互相重叠的Patmax特征无缝拼接
请参考“TB_Patmax算法拼.vpp”; 此VPP实现3张图像上下拼接,其他拼接组合可以自行改写程序
流程:
1).添加Patmax工具,训练各个重叠特征;注意相邻的两张图同样的特征使用同一个Patmax工具即可;
2).载入第一张图像,运行整个CogJob,将图像给到TB_StitchImage1,Patmax定位结果给到Image1Pose1;注意不要用连线;
3).对其他图像重复同样的工作,中间的图像有两个PMA结果,需要连2个Pose;
4).TB_Stitch输出的图像即为拼接后图。


这里CogImageStitch类使用的方法:
1).AllocateBlendingBuffer,指定图像大小为拼接后图的尺寸,Transform不需要特别设置,在(0,0)附近即可,Scale为1;
2).分别为3张图建立CogTransform2DLinear;第一个Transform建立在(0,0)位置, 其他图Transform关系依次Compose 前一个相邻Pose的Invert,因为后一个是依据前一个的位置关系来偏移的。以上下3张图拼接为例,就建立了图示的关系;
3).将图像和Tansform关系分别传入不同的CogFixtureTool,在图像中添加对应的坐标系。注意坐标系名称不能一样;或者用代码AddSpace手动添加坐标系也可以;
4).生成的带新坐标系的图像传入CogImageStitch工具,用BlendImageIntoBuffer方法,会将每张图像对应添加到拼接大图的对
应位置。
5).调用FillDestinationImageFromBuffer来生成拼接图,完成。
注意BlendImageInfoBuffer和OverwriteImage两种方法的区别,Overwrite在像素重叠部分是互相覆盖了,而Blend模式是按照不同权重混合起来,因此更接近无缝拼接。
详细代码如下:
public override bool GroupRun(ref string message, ref CogToolResultConstants result){// To let the execution stop in this script when a debugger is attached, uncomment the following lines.// #if DEBUG// if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();// #endifCogImage8Grey Img1 =(CogImage8Grey) this.Inputs.Image1;CogImage8Grey Img2 =(CogImage8Grey) this.Inputs.Image2;CogImage8Grey Img3 =(CogImage8Grey) this.Inputs.Image3;CogImage8Grey StitchedImg = new CogImage8Grey(Img1.Width+500, Img1.Height * 3);CogImageStitch mStitch = new CogImageStitch();// CogImageStitch.FillDefaultWeightImage(StitchedImg);CogImage8Grey imgMask0 = new CogImage8Grey(Img1.Width, Img1.Height);CogImageStitch.FillDefaultWeightImage(imgMask0);CogImage8Grey imgMask1 = new CogImage8Grey(Img1.Width, Img1.Height);CogImageStitch.FillDefaultWeightImage(imgMask1);CogImage8Grey imgMask2 = new CogImage8Grey(Img1.Width, Img1.Height);CogImageStitch.FillDefaultWeightImage(imgMask2);CogTransform2DLinear trans = new CogTransform2DLinear();trans.Scaling = 1;trans.TranslationX = 10;trans.TranslationY = 10;mStitch.AllocateBlendingBuffer(Img1.Width+500, Img1.Height * 3, trans);CogCoordinateSpaceTree mSpace1 = Img1.CoordinateSpaceTree;CogCoordinateSpaceTree mSpace2 = Img2.CoordinateSpaceTree;CogCoordinateSpaceTree mSpace3 = Img3.CoordinateSpaceTree;CogTransform2DLinear mTrans1 =new CogTransform2DLinear();mTrans1.Scaling = 1;mTrans1.TranslationX = 0;mTrans1.TranslationY = 0;mTrans1.Rotation = 0;// mSpace1.AddSpace("@", "foo_0", mTrans1, true, CogAddSpaceConstants.ReplaceDuplicate);CogTransform2DLinear mTrans2 =this.Inputs.Image2Pose1.Compose(this.Inputs.Image1Pose1.Invert());// mSpace2.AddSpace("@", "foo_1", mTrans2, true, CogAddSpaceConstants.ReplaceDuplicate);CogTransform2DLinear mTrans3 = this.Inputs.Image3Pose2.Compose(this.Inputs.Image2Pose2.Invert()).Compose(mTrans2);// mSpace3.AddSpace("@", "foo_2", mTrans3, true, CogAddSpaceConstants.ReplaceDuplicate);/* mStitch.BlendImageIntoBuffer(Img1, null);mStitch.BlendImageIntoBuffer(Img2, null);mStitch.BlendImageIntoBuffer(Img3, null);*/ this.Tools.CogFixtureTool1.RunParams.UnfixturedFromFixturedTransform = mTrans1;this.Tools.CogFixtureTool1.Run();this.Tools.CogFixtureTool2.RunParams.UnfixturedFromFixturedTransform = mTrans2;this.Tools.CogFixtureTool2.Run();this.Tools.CogFixtureTool3.RunParams.UnfixturedFromFixturedTransform = mTrans3;this.Tools.CogFixtureTool3.Run();mStitch.BlendImageIntoBuffer((CogImage8Grey)this.Tools.CogFixtureTool1.OutputImage, imgMask0);mStitch.BlendImageIntoBuffer((CogImage8Grey)this.Tools.CogFixtureTool2.OutputImage,imgMask1);mStitch.BlendImageIntoBuffer((CogImage8Grey)this.Tools.CogFixtureTool3.OutputImage,imgMask2); mStitch.FillDestinationImageFromBuffer(StitchedImg);// MessageBox.Show(mTrans3.TranslationX.ToString() + " " + mTrans3.TranslationY.ToString());this.Outputs.StitchedImage = StitchedImg;return false;}
3.使用标定板拼接
请参考“TB_标定板拼.vpp”; 此VPP实现3张图像上下拼接,其他拼接组合可以自行改写程序,标定板可以使用二维码标定板,也可以用Cognex标准标定板;
如果使用二维码标定板,不要求视野重叠,使用带 Cognex标记的标定板,则需要视野重叠,以便于各个拍照位置建立统一的标定板坐标系。
流程如下:
1).标定板放好,固定不动。大小要能够覆盖整个拍照视野范围 2).3只相机或同一个相机的3个位置对标定板拍照,执行。
CheckBoard标定;得到outputImage和OutputImageMask;注意此时每张图的输出坐标系都是标定片坐标系;
3).打开距离标定板坐标系原点最近的那张图,获取坐标原点在Root
space下的X和Y坐标值;利用标定板图计算图像的像素坐标与标定板坐标系的比例关系;分别输入到 ToolBlock的dScale,dTransX, dTransY中;
4).执行ToolBlock,即可得到拼接后图像。

CogImageStitch类使用的方法:
1).由于各张子图像已经采用标定板建立了标定板坐标系,因此前面特征拼接方法不同的是,这里不需要再自行建立坐标系关系,使用标定板坐标系即可;
2).但是在AllocateBlendingBuffer时,需要指定RootFromBlendingBuffer的坐标系变换关系。由于BlendingBuffer分配时使用的标定板坐标系,而图像是从rootspace下copy像素,因此变换关系的比例和Translation需要在定义BlendingBuffer时指定。
3)其他部分按照CogImageStitch的使用方法调用即可。
详细代码如下:
public override bool GroupRun(ref string message, ref CogToolResultConstants result){// To let the execution stop in this script when a debugger is attached, uncomment the following lines.// #if DEBUG// if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();// #endifCogImage8Grey Img1 =(CogImage8Grey) this.Inputs.Image1;CogImage8Grey Img2 =(CogImage8Grey) this.Inputs.Image2;CogImage8Grey Img3 =(CogImage8Grey) this.Inputs.Image3;CogImage8Grey imgMask0 = (CogImage8Grey) this.Inputs.CalibMask1;CogImage8Grey imgMask1 = (CogImage8Grey) this.Inputs.CalibMask2;CogImage8Grey imgMask2 = (CogImage8Grey) this.Inputs.CalibMask3;CogImage8Grey StitchedImg = new CogImage8Grey(Img1.Width+500, Img1.Height * 3+500);CogImageStitch mStitch = new CogImageStitch();// CogImageStitch.FillDefaultWeightImage(StitchedImg);CogImage8Grey imgWeight0 = new CogImage8Grey(Img1.Width, Img1.Height);CogImageStitch.FillDefaultWeightImage(imgWeight0);CogImage8Grey imgWeight1 = new CogImage8Grey(Img2.Width, Img2.Height);CogImageStitch.FillDefaultWeightImage(imgWeight1);CogImage8Grey imgWeight2 = new CogImage8Grey(Img3.Width, Img3.Height);CogImageStitch.FillDefaultWeightImage(imgWeight2);CogTransform2DLinear trans = new CogTransform2DLinear();trans.Scaling = this.Inputs.dScale;trans.TranslationX = this.Inputs.dTransX;trans.TranslationY = this.Inputs.dTransY;mStitch.AllocateBlendingBuffer(Img1.Width+500, Img1.Height * 3+500, trans);mStitch.BlendImageIntoBuffer(Img1, imgWeight0,imgMask0,0,0);mStitch.BlendImageIntoBuffer(Img2,imgWeight1,imgMask1,0,0);mStitch.BlendImageIntoBuffer(Img3,imgWeight2,imgMask2,0,0); mStitch.FillDestinationImageFromBuffer(StitchedImg);// MessageBox.Show(mTrans3.TranslationX.ToString() + " " + mTrans3.TranslationY.ToString());this.Tools.CogBlobTool1.InputImage = StitchedImg;this.Tools.CogBlobTool1.Run();return false;}
总结:
1.小视野多次取像,每张图片单独使用检测工具,精度可满足需求;
不够直观,调试复杂;
2.小视野多次取像,根据标定结果,进行图像拼接;
精度可满足需求;同时更加直观,客户接受度高;检测工具使用更加方便;后期维护及设备复制更省心;
相关文章:
VisionPro软件Image Stitch拼接算法
2D图像拼接的3种情景 1.一只相机取像位置固定,或者多只相机固定位置拍图,硬拷贝拼图,采用CopyRegion工具实现 2.一只或多只相机在多个位置拍照,相机视野互相重叠,基于Patmax特征定位后,无缝 拼图ÿ…...
【从零开始入门unity游戏开发之——unity篇09】unity6基础入门——Unity游戏对象和组件的本质、Unity中的反射机制
文章目录 一、Unity游戏对象和组件的本质1、开发游戏的本质2、万物之根本——空对象2.1 什么是空对象?2.2 创建空对象 3、Unity游戏对象的本质4、 transform组件4.1 transform组件的重要性4.2 修改transform的值4.4 **Transform的作用**4.3 重置transform的值 5、总…...
【Linux】深入理解文件系统(超详细)
目录 一.磁盘 1-1 磁盘、服务器、机柜、机房 📌补充: 📌通常网络中用高低电平,磁盘中用磁化方向来表示。以下是具体说明: 📌如果有一块磁盘要进行销毁该怎么办? 1-2 磁盘存储结构 编辑…...
MoEs and Transformers 笔记
ref:https://huggingface.co/blog/zh/moe#%E7%94%A8router-z-loss%E7%A8%B3%E5%AE%9A%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83 MoEs and Transformers Transformer 类模型明确表明,增加参数数量可以提高性能,因此谷歌使用 GShard 尝试将 Transformer 模型…...
在Linux中,如何禁用root用户直接SSH登录?
在Linux中禁用root用户的直接SSH登录是为了增强系统的安全性,因为允许root用户通过SSH远程登录会增加服务器被暴力破解的风险。以下是在Linux系统中禁止root用户直接SSH登录的步骤: 编辑SSH配置文件: 打开/etc/ssh/sshd_config文件ÿ…...
用Python实现简单的任务自动化
目录 1. 自动发送邮件提醒 2. 自动备份文件 3. 自动下载网页内容 总结 在现代工作和生活中,任务自动化可以极大地提高效率和准确性。Python,作为一种功能强大且易于学习的编程语言,是实现任务自动化的理想选择。本文将通过几个简单而实用的案例,展示如何用Python实现任…...
为AI聊天工具添加一个知识系统 之26 资源存储库和资源管理器
本文要点 资源存储库 为了能完成本项目(“为AI聊天工具增加一个知识系统”,其核心能力是“语言处理” ,该能力的最大挑战 当仁不让的应该是自然语言处理)的设计,我们考虑一个问题:在自然语言处理中&#…...
Windows10环境下安装RabbitMq折腾记
最近有个老项目需要迁移到windows10环境,用的是比较老的rabbitmq安装包,如下所示。经过一番折腾,死活服务起不来,最终果断放弃老版本启用新版本。现在把折腾过程记录下: 一、安装erlang 安装完成后的目录结构ÿ…...
对快速由表及里说拜拜/如何正确运用由表及里
你是不是还:看到一男子拖走一女子就以为小情侣吵架而已(可能人贩子);看到男友对你好个几次就从此死心塌地(可能有手就行,细节装装而已)结果耽误终身;看到女同事对你微笑不排斥就以为…...
spring mvc源码学习笔记之八
本文说点儿简单的。 如果你想研究基于 XML 配置的 spring mvc 的话,可以简单扫一眼本文。 在基于 XML 配置的 spring mvc 开发中,我们主要就是通过 spring 提供的各种标签来配置。 但是,大家是不是都有个疑问,spring 到底给我们提…...
探秘5网口IIOT网关
在当今这个科技飞速发展的时代,工业领域正经历着一场深刻的变革,而工业物联网网关在其中扮演着至关重要的角色。 什么是IIOT网关 工业物联网网关,简单来说,就是连接工业现场设备与云端或者上层管理系统的关键桥梁。 而明达技术研…...
左神算法基础巩固--5
文章目录 前缀树生成前缀树查询前缀树查询字符串加入过几次查询所有加入的字符串中,有几个是以pre这个字符串作为前缀 删除前缀树中的某个字符串 贪心算法解题 前缀树 生成前缀树 要想生成一棵前缀树,需要先创建一个根节点,这个根节点有26条…...
Python的Matplotlib库应用(超详细教程)
目录 一、环境搭建 1.1 配置matplotlib库 1.2 配置seaborn库 1.3 配置Skimage库 二、二维图像 2.1 曲线(直线)可视化 2.2 曲线(虚线)可视化 2.3 直方图 2.4 阶梯图 三、三维图像 3.1 3D曲面图 3.2 3D散点图 3.3 3D散…...
负载均衡服务器要怎么配置?
目录 一、概述: 二、硬件配置: 三、操作系统配置: 四、负载均衡软件: 五、网络配置: 六、软件安装步骤: 6.1 安装 Nginx 6.2 安装 LVS 6.3 安装 HAProxy 6.4 安装 Keepalived 一、概述࿱…...
CANopen转EtherCAT网关连接伺服驱动
在现代工业自动化领域,CANopen和EtherCAT是两种常见的通信协议,各自在不同的应用场景中发挥着重要作用。然而,随着工业自动化系统的日益复杂化,不同设备间的通信需求也变得多样化。因此,如何实现不同协议设备之间的无缝…...
自动化测试脚本实践:基于 Bash 的模块化测试框架
前言 在现代软件开发中,测试自动化是确保软件质量和稳定性的核心手段之一。随着开发周期的缩短和功能模块的增多,手动测试逐渐无法满足高效性和准确性的需求。因此,测试人员需要依赖自动化工具来提升测试效率,减少人为干预和错误。…...
WebSocket 测试入门篇
Websocket 是一种用于 H5 浏览器的实时通讯协议,可以做到数据的实时推送,可适用于广泛的工作环境,例如客服系统、物联网数据传输系统, 基础介绍 我们平常接触最多的是 http 协议的接口,http 协议是请求与响应的模式&…...
Apache Traffic存在SQL注入漏洞(CVE-2024-45387)
免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...
Centos7使用yum工具出现 Could not resolve host: mirrorlist.centos.org
在 CentOS 7 中使用 yum 工具时,出现 "Could not resolve host: mirrorlist.centos.org" 的错误,一般情况是因为默认的镜像源无法访问。 以下是一些常用的解决方法: 检查网络连接:首先使用 ping 命令测试网络连接是否…...
zookeeper shell操作和zookeeper 典型应用(配置中心、集群选举服务、分布式锁)
文章目录 引言I zookeeper客户端命令查看子节点 ls创建子节点 create获取节点信息 get更新节点数据 set删除节点 delete\ rmrII 监听机制node1:设置监听node3:修改监听节点node1:得到监听反馈III zookeeper 典型应用分布式锁集群选举服务数据发布/订阅(配置中心)引言 zk 的…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
