ApolloStudio高手之路(12)(机器视觉图像匹配定位与激光打标领域深度结合(基于海康威视VisionMaster九点标定、模板快速匹配定位、标定转换以及金橙子EzCad2二次开发))
在激光标记领域已越趋成为自动化行业中在质量追溯体系管控环节不可或缺的重要一环的今天,传统的标记方式已不能满足于各类综合性比较强的项目需要了,从而结合越来越多新技术的案例也变得更多了起来,现在我们将一起探讨下机器视觉图像匹配定位技术与传统的激光标刻相结合的一个案例(本文中将展示笔者提出的一种坐标系转换思路和方法,当然这肯定不是唯一的,有兴趣的读者可以自行探索更多的解决问题思路,也欢迎将更优秀的新思路分享给我)。
图像匹配定位打标技术的使用已经贯穿了我们日常生活用品中的方方面面,尤其在我们使用的3C电子产品中,小到其组成芯片上的铭文标识,大到其品牌Logo的标识,只要是人们对细节(这里主要是标记位置的定位精度)的追求越多,那么该技术所适用的领域也越来越广泛。
这是一个综合性比较强的项目案例分析讲解,为了方便更好的消化本文所涉及ApolloStudio中的使用要点,可以回顾下之前的两篇文章:
ApolloStudio高手之路(4):用Python以最轻便的方式进行金橙子激光打标板卡二次开发(以EzCad2为载体二次开发)
ApolloStudio高手之路(5):嵌入海康威视VisionMaster机器视觉算法平台提供一站式工控设计
原理剖析 图像匹配定位有一个绕不开的话题:图像坐标系与现实物理坐标系之间的转换。在本案例中,我们主要面对的是一个XY二维平面坐标系之间的转换(即打码机的成像标记平面与面阵相机成像平面平行,3D打码应用不在本篇讨论范畴,故默认Z轴高度方向始终保持0)。
坐标系约定
本文中所约定的打刻机与相机之间的相对位置安装方式不是唯一的解决方案,只不过改变安装方式后需重新规划坐标系转换参数,读者可以根据自身需求和安装条件自行规划。
打码机的打码成像方向与正向放平一本书后字体方向一致(即文字头上底下,打码机光路安装部分无要求,只需最终打刻面方向与此一致即可):
【ApolloStudio高手之路(12)(机器视觉图像匹配定位与激光打标领域深度结合(基于海康威视VisionMaster九点标定、模板快速匹配定位、标定转换以及金橙子EzCad2二次开发))】
文章图片
面阵相机的安装孔面背向操作员(即安装孔的背面面向操作员,安装孔面指向打码机的机体,镜头垂直向下)。
依照上面安装方式,我们可以确定打码机与面阵相机的相对位置对应关系(以相机的视角来看):
文章图片
坐标系转换
约定完坐标系后,我们回过头来思考下我们要达到什么样的目的?在硬件设施根据使用现场情况根据工作距离以及分辨精度选型完成后(选型部分非常重要,直接决定最终项目的成败,但不同项目有差异,故本文的重点只在于阐述原理以及软件实现流程),将指定的工件置于相机视野覆盖范围内,任意数量(不超过视觉软件最大设定的识别个数),视野内任意坐标以及角度,均能稳定的将需要标记的内容刻印上去,实现流水线式自动化操作。
为实现上述目的,我们可以分析到,最终视觉软件只需要输出的技术参数指标有4个:匹配识别的数量、匹配工件的X物理坐标(标定转换后)集合、匹配工件的Y物理坐标(标定转换后)集合以及匹配工件的角度集合。
现在假设我们已经拿到了上面的4组数据,那又如何与打码机的物理坐标系进行关联呢?我们以1个工件的识别为例来分析,首先在相机正下方放置好工件后我们在视觉里面建好匹配模板,同时记录下此时匹配模板的中心值数据(该数据为标定转换后的物理坐标数据),此时不要移动该工件,继续打开EzCAD2软件,将需要标记的内容以及打刻工艺参数设置好,保存打刻模板。操作完成后,我们来看下下面这张平面原理图(以打刻机表面为参考坐标系):
文章图片
在上一步中,我们记录了建立图像模板时的模板中心物理坐标值,我们将该坐标与打刻机的坐标系还原到同一平面分析,从模板图像到无人值守拍照下的任意位置角度目标定位状态,对于工件而言,实际上只是先围绕模板中心旋转了一个夹角差值后,然后平移了XY坐标的差值(即
文章图片
)。
程序实现 在了解原理流程之后,程序方面就好处理了,这里我们以海康威视的VisionMaster(以下简称VM)作为案例进行讲解,视觉部分处理流程分两个步骤进行:首先九点标定,获取相机像素坐标系与打刻机物理坐标系之间的标定文件;之后再通过匹配定位获取工件的个数、X、Y以及A(角度)信息,然后带入标定文件将物理坐标系转换结果输出。
机器视觉处理
九点标定
在这个案例中我们并没有使用到标定板,而是使用了一种更为方便的方式,取一张空白的黑色金属卡片,在激光打码机的EzCAD2上编辑9个实心圆,每个圆直径5mm,每个实心圆圆心与临近实心圆圆心之间的间距固定为20mm,打刻后的效果图为:
文章图片
通过VM的找圆工具,可以通过手动拖动识别框,依次获取9个圆圆心的坐标位置(获取圆心X,Y即可),然后依次填入VM中的“N点标定”数据中。
文章图片
这里有个非常重要的点,物理坐标X与图像坐标X方向相反,而物理坐标Y与图像坐标Y相同,填写内容的时候要注意与图像坐标相对应的物理坐标的正负号,建议如果对该方式不太理解的话,建议用笔和纸把每个点的对应坐标写出来,来完成对应的“填空题”,比如像下面这样:
文章图片
剩余部分调整下物理坐标参数即可,生成标定文件:
文章图片
模板定位流程
模板定位流程比较简单,大家看下流程图既可了解:
文章图片
先取像》定位模板》把定位的数据以标定文件进行物理坐标系转换》通过脚本对转换后的结果进行组合整理,按照我们需要的格式进行处理,然后将结果打包成一个字符串,输出给格式化结果,方便ApolloStudio进行数据捕捉。
这里有个比较重要的细节问题,在上面的视觉流程项目文件中视觉模板建立之后,必须在VM里面直接单击单次执行按钮执行一次,因为此时处于模板刚刚建立阶段,匹配分数应该是最高的时候,这时需要将格式化的结果记录下来,这里的结果将是当前模板匹配中心点转换后的X,Y以及匹配识别框的角度值,将这3个关键信息记录下,填入ApolloStudio脚本中打码初始化对应的三个变量init_X,init_Y,init_A中,后面所有的识别目标都将是以此基础点作为旋转和偏移,这个细节非常重要!
这里的脚本里面我们在输入变量里面获取了匹配的个数,角度值,转换后的物理坐标X以及Y,这4个重要的信息,我们使用脚本的目的是为了将这里面包含的信息进行打包,生成一个字符串输出,下面附上脚本内容:
using System;
using System.Text;
using System.Windows.Forms;
using System.Collections.Generic;
using Hik.Script.Methods;
class UserScript:ScriptMethods,IProcessMethods
{
//执行次数计数
int marknum = 0;
float []bx=new float [20];
float []by=new float [20];
float []ba=new float [20];
///
/// 预编译时变量初始化
///
public void Init()
{}///
/// 流程执行一次进入Process函数
///
///
public bool Process()
{
GetIntValue("marknum", ref marknum);
if (marknum > 0)
{
GetFloatArrayValue("arr_x", ref bx, out marknum);
GetFloatArrayValue("arr_y", ref by, out marknum);
GetFloatArrayValue("arr_a", ref ba, out marknum);
string myres = "";
for ( int i = 0;
i < marknum;
i++)
{
myres = myres + bx[i] + "," + by[i] + "," + ba[i] + "@";
}
myres = myres.Substring(0, myres.Length - 1);
SetStringValue ("finalres", myres);
}
else
{
SetStringValue ("finalres", "NG");
}
return true;
}
}
脚本的格式是根据匹配的个数来判断是否定位成功,成功则发所有的定位数据,失败则发NG。
ApolloStudio数据处理
根据ApolloStudio高手之路(5):嵌入海康威视VisionMaster机器视觉算法平台提供一站式工控设计的经验,我们直接上代码来说明用途:
#-*- coding: UTF-8 -*-
#加载内嵌模块
import clr,sys,time,datetime#初始化海康视觉平台
mystr = "C:\\Program Files (x86)\\VisionMaster3.0.0\\Applications\\VisionMaster.exe"#VM安装路径
mysol = "D:\\ModelFiles\\test.sol"#视觉方案文件路径
modelpath = "D:\\ModelFiles\\test.ezd"#打码模板文件路径
AS.Func_HIK_VM_BindingImg("image1")#绑定显示框
AS.Func_HIK_VM_Init(mystr)#初始化平台
#打码初始化
init_X = 0.0#这里需要填写建立视觉模板时,模板匹配得到的初始X值
init_Y = 0.0#这里需要填写建立视觉模板时,模板匹配得到的初始Y值
init_A = 0.0#这里需要填写建立视觉模板时,模板匹配得到的初始A值
#数据准备
time.sleep(0.5)#等待初始化完成
AS.Func_HIK_VM_LoadSolution(mysol)#加载视觉方案
AS.Func_LM_JCZ_LoadMarkFile(modelpath)#加载打码模板
#循环函数体
while True:
if AS.Func_UI_Button_GetValue(0):#按钮触发
AS.Func_UI_Button_SetValue(0, False)#复位按钮触发标志位
AS.Func_SysInfoAdd("视觉正在识别...")
AS.Func_HIK_VM_ExecuteOnce(10000)#执行方案中编号为10000的流程
myres = AS.Func_HIK_VM_GetFinalData()#获取视觉流程中格式化结果
if (myres != "") and (myres != "NULL") :
AS.Func_SysInfoAdd("视觉结果:" + myres)#获取回传图像数据
if myres == "NG":
AS.Func_UI_Notify("视觉定位失败!", "red", 3)
continue
resall = myres.split('@')#区分多个结果
AS.Func_SysInfoAdd("识别到的个数" + str(len(resall)))
for finallres in resall:#依次打印
my_x = float(finallres.split(',')[0])
my_y = float(finallres.split(',')[1])
my_a = float(finallres.split(',')[2])
delta_X = my_x - init_X#获取X坐标差值
delta_Y = my_y - init_Y#获取Y坐标差值
delta_A = my_a - init_A#获取A坐标差值
AS.Func_LM_JCZ_SetRotateMoveParam(delta_X, delta_Y, init_X, init_Y, - delta_A / 180 * 3.14159265)#旋转打刻
AS.Func_LM_JCZ_DoMark(False)#开始打刻
AS.Func_SysInfoAdd("打码完成!")
else:
AS.Func_UI_Notify("视觉定位失败!", "red", 3)
time.sleep(0.1)
脚本的流程是通过按钮触发,开始执行加载的流程,然后捕获视觉脚本内部的“格式化结果”,根据结果的数据进行解析,将数据传递给打码机进行打刻。
***********************************************************************************************************************************************
ApolloStudio最新版下载地址(网盘有交流群号):
(点击跳转至首页文章,见文章最底部下载链接)
推荐阅读
- 定投,开启个人品牌之路
- 财富自由之路
- 《通往财富自由之路》人生的终极问题到底是什么()
- 读李笑来老师的“财富自由之路”7/365
- 读《财富自由之路》有感
- 99_读|99_读 被讨厌的勇气_岸见一郎
- 复盘学习《通往财富自由之路》专栏——“我们重新理解了付费”
- 《自由财富自由之路Ⅱ》感悟20???榜样
- 【精读营记录】-《财富自由之路》
- 通向自强之路《雨岩仙观图》元·黄公望|通向自强之路《雨岩仙观图》元·黄公望 赏析