Halcon 3D应用 - 胶路提取

1. 需求

本文基于某手环(拆机打磨处理)做的验证性工作,为了项目保密性,只截取部分数据进行测试。
这里使用的是海康3D线激光轮廓相机+直线电机的方式进行的高度数据采集,我们拿到的是高度图+亮度图数据。
提取手环上的胶路信息,检测胶路的胶宽、胶高、断胶等信息。

2.实现思路

  • 扫描没有涂胶水的手环作为模板数据,包含高度图+亮度图;
  • 扫描带胶水的手环作为被测数据,包含高度图+亮度图;
  • 分割模板数据高度图中一个公共部分作为匹配模板;
  • 高度图转点云图,利用模板点云信息,和被测数据的点云进行匹配靠模;
  • 匹配后的点云转高度图;
  • 高度图差分,只保留胶路数据;
  • 进行胶路分析。

3.图像格式分析

3.1高度图

海康相机返回的高度图是tiff格式,具体含义如下:

  • 图像高:直线电机移动中会触发拍照,每拍一次生成一个轮廓,高度对应了本次扫描拍摄的轮廓数。每行的间隔对应了直线电机的触发拍照两次间隔移动的距离。
  • 图像宽:和相机的X轴轮廓点数+X轴采样间隔有关,注意这里不等于轮廓点数,需要调节合适的参数,保证图像的行间隔和列间隔实际距离一致。
  • 像素值:代表高度信息,单位um。

本次测试调节的每个像素宽高都为40um。

3.2亮度图

最终提取的胶路,可以在亮度图上进行对比查看。
亮度图还可以进行缺陷检测、2D匹配定位等功能,但注意本验证中,亮度图不能用来匹配,因为手环放置的位姿可能会出现倾斜透视,需转到点云上进行3D位姿匹配。

4.代码实现

4.1 胶水和无胶水图像信息

无胶水高度图:
在这里插入图片描述
无胶水亮度图:
在这里插入图片描述
带胶水高度图:
在这里插入图片描述
带胶水亮度图:
在这里插入图片描述

4.2 读取数据

read_image(HeightImg_no_glue, height_img_no_glue_path)
read_image (LumImage_no_glue, lum_img_no_glue_path)
read_image(HeightImg_glue, height_img_glue_path)
read_image (LumImage_glue, lum_img_glue_path)get_image_type (HeightImg_no_glue, ImgType) //海康是uint2
get_image_size (LumImage_no_glue, Width, Height)* 裁剪图片
crop_row_begin := 700
crop_row_end := 1060
gen_rectangle1 (ROI_Crop, crop_row_begin, 0, crop_row_end, Width)
reduce_domain (HeightImg_no_glue, ROI_Crop, HeightImg_no_glue)
reduce_domain (LumImage_no_glue, ROI_Crop, LumImage_no_glue)
reduce_domain (HeightImg_glue, ROI_Crop, HeightImg_glue)
reduce_domain (LumImage_glue, ROI_Crop, LumImage_glue)get_image_size (LumImage_no_glue, Width, Height)
dev_open_window (0, 0, Width/2,Height/2, 'black', WindowHandle)* 高度图像素间隔 单位um
step := 40

4.3 高度图预处理

高度图中干扰信息太多,比如底平面、高位杂质等,通过设定高度阈值,去除干扰的信息,聚焦胶水和模板位置的信息。

* 对高度图阈值分割
height_min := 3000  
height_max := 7500
threshold (HeightImg_no_glue, region, height_min, height_max)
reduce_domain (HeightImg_no_glue, region, HeightImg_no_glue)
threshold (HeightImg_glue, region, height_min, height_max)
reduce_domain (HeightImg_glue, region, HeightImg_glue)

预处理结果:
在这里插入图片描述
在这里插入图片描述

4.4 模板位置提取

在高度图中,尽心如下位置的提取:

* 分割模板区域
thr_min := 3500 
thr_max := 4500
gen_rectangle1 (ROI_1, 937, 118, 1060, 220) //选择这个两个孔的位置作为模板
reduce_domain (HeightImg_no_glue, ROI_1, HeightImg_no_glue_roi)
threshold (HeightImg_no_glue_roi, HeightImg_no_glue_roi_region, thr_min, thr_max)//缩小高度范围,聚焦模板平面
reduce_domain (HeightImg_no_glue, HeightImg_no_glue_roi_region, img_mod) //分割模板位置区域,注意是在高度图中分割,这样后面创建的模板3D图像的坐标系和原先的高度图是一样的

提取的模板如下:
在这里插入图片描述

4.5 高度图转点云图

要想进行点云匹配,必须首先将高度图转为点云图。halcon中没有该算子(可能没发现??),这里自己实现了一个算子height_to_3d_obj,可以将高度图转为halcon点云对象。
核心是构建X坐标图、Y坐标图和Z坐标图,然后调用halcon的xyz_to_object_model_3d算子,转为3D图。
三个图的宽高和原始的高度图一致:

  • X图:每个像素存储的是对应高度图相同行列像素的X世界坐标,使用间隔step(高度图像素间隔)构建。可能结果为[(第一行)0 40 80 120 …(第二行)…]
  • Y图:和X图类似,存储的是对应高度图相同行列像素的Y世界坐标,也使用step构建。可能的结果为[(第一行)0 0 0 … (第二行)40 40… ]
  • Z图:就是高度图。

最后需要使用reduce_domain算子只保留原高度图中分割的部分。
在这里插入图片描述

gen_image_const (ImageY, 'real', Width, Height)
gen_image_const (ImageZ, 'real', Width, Height)* 获取高度图中的region区域
get_domain (HeightImg, DomainH)* x图
tupleX :=[]
tuple_gen_sequence (0, (Width-1)*step, step, row_x) //一行
for Index := 0 to Height-1 by 1 //多行拼接成图像数据tupleX :=[tupleX,row_x]
endfor
get_domain(ImageX,domainX)
get_region_points(domainX,rows,cols)
set_grayval (ImageX, rows, cols, tupleX) //技巧,通过获取domain定义域,直接将序列赋值为像素
* 整体赋值完毕后再抠出region
reduce_domain (ImageX, DomainH, ImageX)* y图
tupleY :=[]
for Index := 0 to Height-1 by 1tuple_gen_const (Width, Index*step, row_y)tupleY :=[tupleY, row_y]
endfor
set_grayval (ImageY, rows, cols, tupleY)
reduce_domain (ImageY, DomainH, ImageY)* z图 - 转为real格式的图,原高度图非real格式
get_region_points(DomainH,rows_Z,cols_Z)
get_grayval(HeightImg,rows_Z,cols_Z,tupleZ)
zv0 := tupleZ
set_grayval (ImageZ, rows_Z, cols_Z, zv0) //ImageZ在前面是real格式
reduce_domain (ImageZ, DomainH, ImageZ)xyz_to_object_model_3d (ImageX, ImageY, ImageZ, ObjectModel3D3)
return ()

最后显示三个高度图的点云图像:

*3D对象模型查看
height_to_3d_obj (HeightImg_no_glue, step, obj3D_hk_no_glue)
height_to_3d_obj (HeightImg_glue, step, obj3D_hk_glue)
height_to_3d_obj (img_mod, step, obj3D_mod)
visualize_object_model_3d (WindowHandle, obj3D_hk_no_glue, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)
visualize_object_model_3d (WindowHandle, obj3D_hk_glue, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)
visualize_object_model_3d (WindowHandle, obj3D_mod, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

无胶水:
在这里插入图片描述
胶水:
在这里插入图片描述
模板:
在这里插入图片描述

4.6 点云匹配

先上代码:

* 点云匹配校准
create_surface_model (obj3D_mod, 0.03, [], [], SurfaceModel)//创建surface模型,因为上面的模型非点云型,需进行采样
MinScore := 0.1
* find返回的Pose指的是模型到目标的位姿变换关系,可以用rigid_trans_object_model_3d将模板转换到目标附近靠模
find_surface_model (SurfaceModel, obj3D_hk_glue, 0.03, 0.1, MinScore, 'true', ['num_matches', 'use_3d_edges'], [1, 'false'], Pose_glue, Score, SurfaceMatchingResult)
get_surface_matching_result (SurfaceMatchingResult, 'sampled_scene', [], SampledScene)
get_surface_matching_result (SurfaceMatchingResult, 'key_points', [], KeyPoints)* 胶路点云对齐到模型,注意rigid_trans_object_model_3d算子是将模型转变到目标场景中
* pose_invert (Pose_glue, Pose_glue_Invert)
rigid_trans_object_model_3d (obj3D_hk_no_glue, Pose_glue, obj3D_hk_no_glue_t)
visualize_object_model_3d (WindowHandle, [obj3D_hk_glue,obj3D_modTrans,obj3D_hk_no_glue_t], [], [], \['color_' + [0, 1, 2],'point_size_' + [0, 1, 2],'disp_pose'], ['red', 'blue', 'yellow', 1.0, 3.0, 5.0,'true'], [], [], [], PoseOut)
  • 首先create_surface_model 进行采样,作为基准;
  • find_surface_model 进行点云匹配,返回的Pose是模型到目标的位姿变换关系,这里的参数不再详细解释,需自己实验调节;
  • rigid_trans_object_model_3d 靠模,这里是将模型(无胶水点云)转变到目标场景中(胶水点云),用这个算子就可以进行点云对齐,为后面的高度图差分做准备。

在这里插入图片描述
其中红色的带胶的,黄色是无胶水,蓝色是无胶水的模板。

4.7 点云转高度图

现在需要将靠模后的无胶水点云转为高度图,这里又是自己封装的算子:
在这里插入图片描述

*3D对象中的xyz点云,转为z向高度图
get_object_model_3d_params (object_3d, 'point_coord_x', point_x_no_glue_t)
get_object_model_3d_params (object_3d, 'point_coord_y', point_y_no_glue_t)
get_object_model_3d_params (object_3d, 'point_coord_z', point_z_no_glue_t)
cols := int(point_x_no_glue_t/step) //在高度图中的行列坐标,cols[index]和rows[index]是一对。 
rows := int(point_y_no_glue_t/step) 
* 高度图赋值
for Index := 0 to |cols|-1 by 1* 注意其中可能有负数!下面将负数都转移到0,0* 可能有越界的点,都转移到0if (cols[Index] < 0 or cols[Index]>=Width)cols[Index] :=0rows[Index] :=0point_z_no_glue_t[Index] :=0endifif (rows[Index] < 0 or rows[Index]>=Height)cols[Index] :=0rows[Index] :=0point_z_no_glue_t[Index] :=0endif
endfor
gen_image_const (Height_img, img_type, Width, Height)
set_grayval (Height_img, rows, cols, point_z_no_glue_t) //将对应行列的,设置为对应的z值,比较绕这里。
return ()

实际代码:

* x y z的实际坐标是变了,所以深度图需要由这三个实际坐标来重新构建
obj3D_to_height (Height_img_no_glue_t, obj3D_hk_no_glue_t, step, Width, Height, ImgType)

带胶水的高度图:
在这里插入图片描述

转换之后的高度图(无胶水):
在这里插入图片描述
转换之前的高度图(无胶水):
在这里插入图片描述

4.8 差分

* 差分
sub_image (HeightImg_glue, Height_img_no_glue_t, ImageSub, 1, 0)
threshold (ImageSub, Image_Glue, 80, 1000)

背景为带胶水的亮度图,红色的为差分出的胶路Region:
在这里插入图片描述

5. 胶路分析

略。

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

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

相关文章

Java面向对象编程--高级

目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习&#xff0c;测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…

d3dcompiler_47.dll缺失怎么修复,马上教你六种靠谱的方法

在使用计算机的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中一个就是某些dll文件缺失。比如d3dcompiler_47.dll&#xff0c;这个文件是DirectX的一部分&#xff0c;主要用于编译DirectX的着色器代码。当这个文件缺失时&#xff0c;一些程序就无法正常运行了&…

typescript使用webpack打包编译问题

解决方案&#xff1a;在webpack.config.js中的mdule.exports中设置mode。 再次运行npm run start即可。

pytest的基础入门

pytest判断用例的成功或者失败 pytest识别用例失败时会报AssertionError或者xxxError错误&#xff0c;当捕获异常时pytest无法识别到失败的用例 pytest的fixture夹具 pytest的参数化 #coding:utf-8 import pytestfrom PythonProject.pytest_test.funcs.guess_point import ge…

GAN(Generative Adversarial Nets)

GAN(Generative Adversarial Nets) 引言 GAN由Ian J. Goodfellow等人提出&#xff0c;是Ian J. Goodfellow的代表作之一&#xff0c;他还出版了大家耳熟能详的花书&#xff08;Deep Learning深度学习&#xff09;&#xff0c;GAN主要的思想是同时训练两个模型&#xff0c;生成…

【重磅升级】基于大数据的股票量化分析与预测系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 伴随全球经济一体化和我国经济的快速发展&#xff0c;中国股票市场对世界经济的影响力不断攀升&#xff0c;中国股市已成为全球第二大股票交易市场。在当今的金融市场中&#xff0c;股票价格的波动…

只需5步,就可以使用大语言模型(LLM)打造高效的应用

01 概述 随着人工智能技术的飞速发展&#xff0c;大型语言模型&#xff08;LLM&#xff09;正逐渐成为各个领域的得力助手。从最初的文本理解、生成到翻译&#xff0c;这些模型在自然语言处理&#xff08;NLP&#xff09;中的出色表现&#xff0c;让它们在聊天机器人、虚拟助…

微调大语言模型——超详细步骤

微调一个语言模型&#xff0c;其实就是在一个已经训练过的模型上&#xff0c;继续用新数据进行训练&#xff0c;帮助模型更好地理解和处理这个新的任务。可以把这个过程想象成教一个已经懂很多道理的人去解决新的问题。 这个过程可以分为五个简单的步骤&#xff1a; 加载预训练…

自定义注解和组件扫描在Spring Boot中动态注册Bean(一)

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 在Spring Boot中&#xff0c;自定义注解和组件扫描是两种强大的机制&#xff0c;它们允许开发者以声明性的方式动态注册Bean。这种方式不仅提高了代码的可读性和可维护性&#xff0c;还使得Spring Boot应用的…

动态规划lc

先找到规律&#xff0c;然后找边界情况&#xff1b;部分特殊情况分类讨论 *递归 70.爬楼梯 简单 提示 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a…

UCI-HAR数据集深度剖析:训练仿真与可视化解读

在本篇文章中&#xff0c;我们将深入探讨如何使用Python对UCI人类活动识别&#xff08;HAR&#xff09;数据集进行分割和预处理&#xff0c;以及运用模型网络CNN对数据集进行训练仿真和可视化解读。 一、UCI-HAR数据集分析及介绍 UCI-HAR数据集是一个公开的数据集&#xff0c…

【C++差分数组】P1672何时运输的饲料

本文涉及知识点 C差分数组 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 P1672何时运输的饲料 原文比较啰嗦&#xff0c;我简述一下&#xff1a; 第x天运来F1(1<F1<1e6)千克的饲料&#xff0c;第D&#xff08;1<2e3)天还剩F2&…

树莓派3b安装ubuntu18.04服务器系统server配置网线连接

下载ubuntu镜像网址 img镜像&#xff0c;即树莓派官方烧录器使用的镜像网址 ubuntu18.04-server&#xff1a;ARM/RaspberryPi - Ubuntu Wiki 其他版本&#xff1a;Index of /ubuntu/releases 下载后解压即可。 发现使用官方烧录器烧录配置时配置wifi无论如何都不能使用&am…

Charles安卓抓包环境配置

下载安装Charles 官网搜索然后直接下载就可以了 抓HTTP的包 HTTP代理 在Proxy->Proxy Settings里配置HTTP代理 手机上配置代理 进入WIFI&#xff0c;找到连接的网络&#xff0c;打开高级选项&#xff0c;里面有一个代理选项&#xff0c;将其改为手动&#xff0c;然后…

子网掩码、网络地址、广播地址、子网划分及计算

1. IPV4地址分类及组成 IP地址网络地址主机地址&#xff0c;&#xff08;又称&#xff1a;主机号和网络号&#xff09; 由上图可见网络号和主机号之和是32&#xff0c;而且此多彼少。 例&#xff1a;IP地址为192.168.2.131&#xff0c;转换成二进制1111 1111.1010 1000.0000 00…

小程序知识付费的优势 知识付费服务 知识付费平台 知识付费方法

在信息爆炸的时代&#xff0c;知识如同繁星点点&#xff0c;璀璨而散落。如何在这片知识的海洋中精准捕捞&#xff0c;成为现代人追求自我提升的迫切需求。小程序知识付费&#xff0c;正是这样一座桥梁&#xff0c;它以独特的优势&#xff0c;让智慧触手可及&#xff0c;轻触未…

【宝可梦】游戏

pokemmo https://pokemmo.com/zh/ 写在最后&#xff1a;若本文章对您有帮助&#xff0c;请点个赞啦 ٩(๑•̀ω•́๑)۶

【Java】 —— 数据结构与集合源码:Vector、LinkedList在JDK8中的源码剖析

目录 7.2.4 Vector部分源码分析 7.3 链表LinkedList 7.3.1 链表与动态数组的区别 7.3.2 LinkedList源码分析 启示与开发建议 7.2.4 Vector部分源码分析 jdk1.8.0_271中&#xff1a; //属性 protected Object[] elementData; protected int elementCount;//构造器 public …

数据安全防线:移动应用等保测评在个人信息保护中的作用“

在数字化浪潮席卷全球的当下&#xff0c;移动应用&#xff08;App&#xff09;已成为人们日常生活中不可或缺的一部分。然而&#xff0c;随之而来的个人信息泄露事件频发&#xff0c;引发了社会对数据安全和个人隐私保护的广泛关注。在此背景下&#xff0c;等保测评作为一项重要…

黑马程序员C++提高编程学习笔记

黑马程序员C提高编程 提高阶段主要针对泛型编程和STL技术 文章目录 黑马程序员C提高编程一、模板1.1 函数模板1.1.1 函数模板基础知识 案例一&#xff1a; 数组排序1.2.1 普通函数与函数模板1.2.2 函数模板的局限性 1.2 类模板1.2.1 类模板的基础知识1.2.2 类模板与函数模板1.…