内容回顾	回顾上节课程我们对运动控制+机器视觉的例程demo的系统参数的设置和配方文件的管理两大模块进行了大致的介绍,接下来我们将对相机标定和形状匹配这两个功能进行介绍。
	相机标定的目的是将像素坐标和世界坐标建立关系,形状匹配的目的是获取目标图形在图像中的像素坐标,将相机标定和形状匹配结合即可导出目标图形在空间上的世界坐标。
	01相机标定	一、标定板标定和九点标定的介绍
	1.标定板方式标定
	将标定板放入现场被测物体同一平面,通过相机对标定板进行取像,然后视觉获取标定板图像中n个特征点的像素坐标。接着记录每个特征点的世界坐标。特征点世界坐标获取方式可利用手动运动使机台的探针去对特征点的中心获取。那么使用这n对像素坐标和世界坐标则可对相机进行标定,标定出相机坐标系和世界坐标系转换关系。
	2.九点方式标定
	利用视觉定位特征点的方式获取图像特征点像素坐标,定位特征点可采用的方法有形状匹配、blob定位、圆定位等。首先保证目标不动,机台控制相机以九宫格形式移动九次并拍照采集九幅图像从而获得九个特征点的像素坐标。移动一次拍照视觉定位一次,每次移动拍照时要保证目标在相机视野之内,同时读出机台的世界坐标。那么使用这九对像素坐标和世界坐标进行相机标定,就可以标定出像素坐标系和世界坐标系的转换关系。
	二、九点标定人机界面交互流程分析
	三、标定界面的设计
	先在上一个界面(ccd偏置界面)打开连续采集,然后手动运动使mark点位于相机视野中间。然后进入该界面点击“1.0、显示roi”,通过roi矩形框将mark点进行框选,接着点击“1.1、创建形状模板”。
	形状模板创建完成后进行x间隔和y间隔的设置,然后点击“2、开始自动标定”,等待标定完成即可。
	注意:需要设置合适的间隔,保证九个拍照位都可以拍到mark点。
	四、九点标定代码
'/************************************************************
	           '函数功能:  自动标定
	           'input:    无
	           'output:   无 
	           '返回值:   无
	           '备注:     标定需要一段时间,防止卡界面需要开线程。
	           '*************************************************************/
	           global sub runninecalib()
	                    if gv_curprogrstate=3 then 
	                   '如果是停止状态
	                         stoptask 2
	                         runtask 2,ninecalib()
	                  endif
	         endsub
global sub ninecalib()
	    local lv_cali,lv_calj
	    local lv_dposx, lv_dposy, lv_num
	    zvobject matchscal
	    '设置自动标定速度
	    for i=0 to gc_axisnum-1 
	        speed(i) = 20
	    next
	    '更新自动标定z轴高度
	    table(212) = table(202)
	    '读取模板
	    zv_readshapemod(gv_curshapemod,/zmc/flash/shapecal.zvb)
	    '更新x,y间隔
	    vr(190)=table(250)
	    vr(191)=table(251)
	    '更新第一个拍照位的位置
	    lv_dposx = dpos(gc_axis_x)-vr(190)
	    lv_dposy = dpos(gc_axis_y)-vr(191)
	    lv_num=0
	    '当前状态设置成自动标定状态
	    gv_curprogrstate=4
	    for lv_cali = 0 to 2 
	        for lv_calj = 0 to 2 
	            '每次循环进行移动一次
	            moveabs( lv_dposx + lv_calj * vr(190), lv_dposy + lv_cali * vr(191)) 
	            wait until idle(0) 
	            delay(200)
	            camgrab()
	            '匹配获取像素坐标
	            zv_gaussblur(gv_grabimg, gv_grabimg, 3)
	            zv_shapefind(gv_curshapemod, gv_grabimg, matchscal, gv_match_param(0), gv_match_param(1), gv_match_param(2), gv_match_param(3),                       gv_match_param(4), gv_match_param(5), gv_match_param(6))
	            delay(50)
	            '获取结果
	            table(50)=0
	            zv_matgetrow(matchscal,0,5,50)
	            trace 像素坐标:table(51),table(52)
	            if table(50) < 85 then 
	                ga_operatips=标定ng,请重新标定
	                hmi_showwindow(50,6)
	                '当前状态设置成停止状态
	                gv_curprogrstate=3
	                return 
	            endif
	            '灰度图转rgb图
	            zv_graytorgb(gv_grabimg, gv_shapergbimg)    
	            '计算刚性矩阵
	            zv_getrigidvector(gv_rigidmat, 0, 0, 0, table(51), table(52), table(53))  
	            '进行轮廓仿射变换
	            zv_contaffine(gv_shapecontlist, gv_rigidmat, gv_shapecontlistaff)
	            zv_contlist(gv_shapergbimg, gv_shapecontlistaff, v_green, 0)
	            zv_latchclear(0)
	            zv_latch(gv_shapergbimg, 0)
	            '将像素坐标存入 table 中 
	            table(161 + lv_num*2) = table(51)
	            table(162 + lv_num*2) = table(52)
	            trace 像素坐标,table(51),table(52)
	            '将机台世界坐标存入 table 中 
	            table(181 + lv_num*2) = -(lv_calj * vr(190)) 
	            table(182 + lv_num*2) = -(lv_cali * vr(191))
	            '记录自动标定时物体与相机中心的像素偏移量
	            if lv_cali=0 and lv_calj=0 then
	                vr(103) = table(51)
	                vr(104) = table(52)
	            endif
	            lv_num = lv_num + 1
	        next 
	    next 
	    '将 table 中的像素和世界坐标转换成矩阵存储 
	    zv_matgendata(gv_ppts, 9, 2, 161) 
	    zv_matgendata(gv_wpts, 9, 2, 181) 
	    '九次循环后进行标定
	    gv_calmodeflag=2
	    zv_calcam(gv_ppts, gv_wpts, gv_calparam, gv_photow, gv_photoh, 2)  
	    '计算标定误差,table(0),table(1),table(2)分别为平均误差、最小误差、最大误差 
	    zv_calerror(gv_calparam, gv_ppts, gv_wpts, 0)  
	    table(179) = table(1)  '最小误差
	    table(180) = table(2)  '最大误差
	    table(199) = table(0)  '平均误差
	    ga_operatips=标定ok
	    hmi_showwindow(50,6)
	    '当前状态设置成停止状态
	    gv_curprogrstate=3
	    '设置标志位表示标定成功
	    modbus_bit(152)=1
	endsub
五、标定系数的应用
	下图是相机第一个拍照位的视野情况和加工中心的情况。我们要知道如果系统上面的标定方法标定出来的像素坐标和世界坐标的关系是相机第一个拍照位相机视野上mark点的位置的。
	换句话说就是,如果我们通过视觉获得目标位置的像素坐标,再通过标定系数转换成世界坐标,然后机台通过运动指令进行移动到相应位置,此时对准目标位置的不是相机中心而是向量a的起点位置。
	而在我们实际加工中,是需要加工中心对准该目标位置,根据下图信息可以知。因为向量a的起点和终点的像素坐标已知,向量b也可以通过简单的对点方式计算出来,所以可以很方便地计算出向量c。
像素坐标转世界坐标如下:
02视觉形状匹配	一、形状模板创建和形状模板匹配指令
二、创建形状模板界面设计
	点击“显示roi”,显示出矩形roi区域,通过移动鼠标将感兴趣的区域框选起来,然后点击“创建形状模板”即可完成模板创建。
	三、形状模板创建流程图
四、创建形状模板
	'/************************************************************
	'任务编号:无
	'函数功能:生成模板
	'input:无
	'output:无 
	'返回值:无
	'备注:无  
	'*************************************************************/
	global sub estabshape(mode)
	    if mode  1 then
	        'hmi roi坐标转 图像roi
	        zv_postoimg(0, 2, 74, 0)
	        dv_roipos(0) = table(0)
	        dv_roipos(1) = table(1)
	        dv_roipos(2) = table(2) - table(0) + 1
	        dv_roipos(3) = table(3) - table(1) + 1
	        '生成模板图像
	        zv_imggetsub(gv_grabimg, gv_shapeimg, dv_roipos(0), dv_roipos(1), dv_roipos(2), dv_roipos(3))
	        '生成模板区域
	        zv_regenrect(gv_shapere, 0, 0, dv_roipos(2), dv_roipos(3)) 
	    endif  
	    '开始创建模板
	    '设置创建模板等级
	    zv_setsysint(shapecreatelevel,gv_mod_param(9))
	    '清空之前创建的模板
	    zv_clear(gv_curshapemod)
	    '进行创建模板
	    zv_shapecreatere(gv_shapeimg, gv_shapere, gv_curshapemod, gv_mod_param(0), gv_mod_param(1), gv_mod_param(2), gv_mod_param(3), gv_mod_param(4), gv_mod_param(5), gv_mod_param(6), gv_mod_param(7), gv_mod_param(8))
	    'gv_curshapemod是刚刚创建的模板
	    dv_creamodel = 1
	    '获取模板的轮廓
	    zv_shapecontours(gv_curshapemod, gv_shapecontlist, 0)  
	    '灰度图像转rgb图象(主要绘制轮廓的时候用的)
	    zv_graytorgb(gv_shapeimg, gv_shapergbimg)    
	    '获取图片信息
	    '0是table 索引,图像信息,5 个数据,依次为宽、高、通道数、数据类型和基本像元大小  
	    zv_imginfo(gv_shapergbimg, 0)  
	    zv_getrigidvector(gv_rigidmat, 0, 0, 0, table(0)/2, table(1)/2, 0)  '计算刚性变换矩阵(能对图形进行旋转、平移等变换)    
	    zv_contaffine(gv_shapecontlist, gv_rigidmat, gv_shapecontlistaff)  '轮廓或轮廓序列仿射变换
	    '绘制轮廓  
	    zv_contlist(gv_shapergbimg, gv_shapecontlistaff, v_red, 0)
	    '锁存通道1显示清空    
	    zv_latchclear(1)
	    '显示创建模板的图像    
	    zv_latch(gv_shapergbimg, 1)
	    '跳转到模板编辑界面
	    hmi_showwindow(26,4)
	    '进入模板可编辑状态
	    gv_customtype=2
	    '保存模板
	    if table(211)=0 then
	        '自动标定模板 
	        zv_writeshapemod(gv_curshapemod,/zmc/flash/shapecal.zvb)
	    endif
	    '创建模板后直接进行一次测试
	    shapematch()
	    '模板编辑显示
	    shapeeditshow(0)
	    if mode = 1 then 
	        gv_edgeedit(1)=0  
	    endif
	endsub
五、创建形状模板
	'/************************************************************
	'任务编号:无
	'函数功能:模板匹配
	'input:无
	'output:无 
	'返回值:无
	'备注:无  
	'*************************************************************/
	global sub shapematch() 
	    '更新标定系数
	    update_cal(table(202))
	    gv_customtype=0
	    '分数清零
	    table(3)=0
	    zv_setsysdbl(shapefindtimeout,1000)
	    '进行匹配操作
	    zv_shapefind(gv_curshapemod, gv_grabimg, gv_shapematchrst, gv_match_param(0), gv_match_param(1), gv_match_param(2), gv_match_param(3), gv_match_param(4), gv_match_param(5), gv_match_param(6))  
	    '获取模板轮廓
	    zv_shapecontours(gv_curshapemod, gv_shapecontlist, 0)    
	    '灰度图转rgb图
	    zv_graytorgb(gv_grabimg, gv_shapergbimg)    
	    '获取矩阵行信息
	    zv_matgetrow(gv_shapematchrst, 0, 5, 3)
	    '计算刚性矩阵
	    zv_getrigidvector(gv_rigidmat, 0, 0, 0, table(4), table(5), table(6)) 
	    trace 像素坐标,table(4),table(5)
	    if table(3) < 70 then
	        ?匹配分数,table(3)
	        ga_operatips=匹配失败
	        hmi_showwindow(50,6)
	        emergstoptask()
	    endif 
	    '进行轮廓仿射变换
	    zv_contaffine(gv_shapecontlist, gv_rigidmat, gv_shapecontlistaff)
	    zv_contlist(gv_shapergbimg, gv_shapecontlistaff, v_green, 0)
	    '转换到mark点的实际世界坐标
	    caltransw_offset(table(4), table(5), 223)
	    ?世界坐标1,table(223),table(224)
	    table(223) = table(223)+ table(200)
	    table(224) = table(224)+ table(201)
	    table(225) = table(6)
	    trace 世界坐标,table(223),table(224),table(225)
	    '显示匹配出来将轮廓变绿的图像
	    zv_latchclear(0)
	    zv_latch(gv_shapergbimg, 0)
	endsub
	03相机标定和视觉定位演示视频	本次,正运动技术运动控制+机器视觉demo软件框架(二):移动标定和形状匹配,就分享到这里。
			
			
       	 	
    	未来三年内马斯克是否会为抛弃“激光雷达”而后悔?
         	 	
    	蓝屏代码0x000000d1的原因和解决方法
         	 	
    	苹果20W USB PD快充充电器测评,外壳模具换汤不换药
         	 	
    	研究人员发明可用人眼控制的机器人镜头
         	 	
    	小米6、荣耀9、oppor11对比评测:外观、配置、性能、价格,小米6、华为荣耀9、oppor11你买谁?
         	 	
    	Demo系统的移动标定和形状匹配功能
         	 	
    	华人运通发布智城项目 为未来出行提供实践与方案
         	 	
    	Batch的大小、灾难性遗忘将如何影响学习速率
         	 	
    	四国联合体签署PPA协议,将打破世界最低光伏电价和最大规模发电站
         	 	
    	中国联通正式宣布与中国电信合建5G网络
         
       	 	
    	AI手机到底是创新还是噱头?真的值得买吗?
         	 	
    	最新医疗设备预测并追求您的极限!
         	 	
    	借力‘物联网+’为苏区发展注入新活力
         	 	
    	繁易荣获”2020年度上海市高转项目十强企业”称号
         	 	
    	简单电路从-48V输入提供+5V栅极偏置
         	 	
    	长江存储新技术可轻松实现单盘1TB容量
         	 	
    	电容常见的九大用途
         	 	
    	镍基正极材料(NCM/NCA)正不断取代LMO/LFP的市场
         	 	
    	博文 | 宽能隙元件建构高效节能绿世界
         	 	
    	深度解析全新皇冠2.0T发动机