形状匹配是基于边缘梯度的轮廓相似度搜索匹配功能,经常用于批量生产的具有固定形状的产品的定位检测项目,或者辅助其他视觉检测算法做位置补正功能,但是它只能识别一种形状的产品。
在工业生产环节中,同一个检测工位可能会对不同的物料的多种形状进行分类拾取操作时,需要识别与定位,此时需要可以同时支持匹配多种模板轮廓的功能,因此,我们正运动视觉指令引入了多轮廓匹配的功能。
上期课程,我们讲述了机器视觉方案中齿轮缺齿检测的应用例程,本期课程我们将和大家一起分享如何实现多轮廓匹配的功能。
《教学视频:VPLC系列机器视觉运动控制一体机快速入门(十一)多轮廓匹配》
一 检测原理
多轮廓匹配的检测算法是在形状匹配的基础上增加存储多种模板轮廓信息的列表,创建模板完成后将对应模板信息添加到模板列表中,并生成模板对应的唯一ID(默认ID从0开始,依次递增)。在执行多轮廓匹配时,会将当前图像中的所有目标特征和模板列表进行相似度对比,返回所有满足匹配条件的结果信息,包括分数、位置X、位置Y、角度、比例、模板ID。
二 软件实现
(一)软件实现
1.打开ZDevelop软件:新建项目→新建“HMI”文件→新建“main.bas”文件,用于编写界面响应函数→新建“global_variable.bas”文件用于存放全局变量并开启HMI自动运行任务→新建“InitLocator.bas”文件用于初始化测量参数→新建“camera.bas”文件用于实现相机采集功能→新建draw.bas文件用于更新绘制图形刷新界面→文件添加到项目。
2.设计HMI界面。
3.在“global_variable.bas”文件中定义全局变量,定义完成后运行“Hmi.hmi”文件。
'''''全局变量大部分使用数组结构'''''
''注:basic编程中很多函数会以TABLE(系统的数据结构)做为参数
''table 说明 table 说明
''0~1 获取到的图像宽高 15~18 定位器roi图像坐标数据
''0~1 匹配结果矩阵的行列数 25~28 定位器roi控件和图像数据
''53~62 匹配结果 30~31 橡皮擦roi坐标
''11~12 鼠标操作时获取的坐标 40~46 匹配参数
'***********定义程序任务相关变量**********************
'主任务状态
'0 - 未初始化
'1 - 停止
'2 - 运行中
'3 - 正在停止
GLOBAL DIM main_task_state
main_task_state = 1
'运行任务开关
GLOBAL DIM run_switch
run_switch = 0
'采集任务开关
'0 - 停止采集
'1 - 请求采集
GLOBAL DIM grab_switch
grab_switch = 0
'定位检测主任务id - 10
GLOBAL DIM main_task_id
main_task_id = 10
'相机连续采集线程id - 7
GLOBAL DIM grab_task_id
grab_task_id = 7
'***********结束定义程序任务相关变量******************
'***********定义相机采集相关变量**********************
'相机种类,此处使用海康相机-"mvision"
GLOBAL DIM CAMERA_TYPE(100)
'CAMERA_TYPE = "mindvision;basler;mvision;huaray;zmotion"
CAMERA_TYPE = "mvision"
'相机个数
GLOBAL cam_num
cam_num = 0
'相机模式,-1 连续采集,0-软件触发采集
GLOBAL cam_mode
cam_mode = 0
'***********结束定义相机采集相关变量******************
'定义返回主界面标志,1-已返回,0-未返回
GLOBAL DIM d_is_rtn_loc
d_is_rtn_loc = 1
'***********定义模板相关变量*************************
'定义鼠标按下标志位,1-已按下,0-未按下
GLOBAL DIM is_set_roi_m_down
is_set_roi_m_down = 0
'定义创建模板标志位,1-已创建模板,0-未创建模板
GLOBAL DIM d_is_creModel
d_is_creModel = 0
'学习模板参数,starAngle、endAngle、minScale、maxScale、thresh、numlevel、reduce、angleStep、scaleStep
GLOBAL DIM d_mod_param(9)
'***********结束定义模板相关变量**********************
'***********定义编辑模板相关变量*********************
'定义编辑模板标志,0-表示不编辑模板,1-表示编辑模板
GLOBAL DIM d_edit_m
d_edit_m = 0
'定义使用橡皮擦功能标志,0-表示恢复擦除的区域,1-表示擦除区域
GLOBAL DIM d_isMask_m
d_isMask_m = 1
'定义橡皮擦的roi参数,依次是矩形左上角和右下角图像坐标x、y、x、y
GLOBAL DIM d_locator_roi(4),d_eraser_roi(4)
'定义正方形橡皮擦尺寸宽度
GLOBAL DIM d_eraser_size
d_eraser_size = 5
'定义界面控件上橡皮擦的矩形区域
GLOBAL DIM c_rect(4)
'定义鼠标状态标志,0-表示鼠标处于松开状态,1-表示鼠标处于按下状态
GLOBAL DIM d_mouse_s
d_mouse_s = 0
'***********结束定义编辑模板相关变量******************
'***********定义匹配检测相关变量*********************
'定义学习模板的roi参数和橡皮擦的roi参数,依次是矩形左上角和右下角图像坐标x、y、x、y
GLOBAL DIM d_locator_roi(4),d_eraser_roi(4)
'匹配结果,score、x、y、angle、scale, 目前对于多目标匹配也只存第一个目标
GLOBAL DIM d_match_rst(5)
GLOBAL DIM d_match_time '定义匹配定位消耗的时间变量
d_match_time = 0
'***********结束定义匹配检测相关变量******************
'定义程序执行过程中缓存中间图片和结果图片的变量
GLOBAL ZVOBJECT grabImg
GLOBAL ZVOBJECT subImg,copy_subImg,colorSubImg, s_mod,modList,mat_param
GLOBAL ZVOBJECT modRe
GLOBAL DIM C_RED, C_GREEN, C_BLUE, C_YELLOW
C_RED = ZV_COLOR(255, 0, 0)
C_GREEN = ZV_COLOR( 0,255, 0)
C_BLUE = ZV_COLOR( 0, 0,255)
C_YELLOW= ZV_COLOR(255,255, 0)
'显示打印的字符
GLOBAL ShowString(64),ShowString1(64)
'***********定义读取本地文件功能相关变量**************
''注意,该功能只在使用仿真器时有效
'定义是否使用本地图片标志
GLOBAL DIM d_use_imgfile
'定义本地图片索引
GLOBAL DIM d_index
'定义读取图片的路径
GLOBAL DIM File_Name(100)
'***********结束定义读取本地文件功能相关变量**********
'初始化全局变量完成后开启HMI文件
RUN"Hmi1.hmi",1
4.在“InitLocator.bas”文件中初始化测量参数。
end
GLOBAL SUB init_meas_param() '初始化测量参数
'初始化定位器roi参数
d_locator_roi(0) = 240 '左上角x
d_locator_roi(1) = 180 '左上角y
d_locator_roi(2) = 400 '右下角x
d_locator_roi(3) = 300 '右下角y
'初始化模板参数
d_mod_param(0) = -180 '起始角度
d_mod_param(1) = 180 '终止角度
d_mod_param(2) = 1 '最小缩放
d_mod_param(3) = 1 '最大缩放
d_mod_param(4) = 80 '阈值
d_mod_param(5) = 0 '默认金字塔层数
d_mod_param(6) = 0 '默认约简特征点
d_mod_param(7) = 0 '默认角度步长
d_mod_param(8) = 0 '默认缩放步长
'初始化匹配测量参数
TABLE(40) = 70 '最小分数
TABLE(41) = 1 '匹配个数
TABLE(42) = 10 '默认最小间距
TABLE(43) = 40 '最小阈值
TABLE(44) = 0 '精度
TABLE(45) = 9 '速度
TABLE(46) = 0 '极性
'初始化匹配定位结果
d_match_rst(0) = 0 '分数
d_match_rst(1) = 0 '位置X
d_match_rst(2) = 0 '位置Y
d_match_rst(3) = 0 '角度
d_match_rst(4) = 0 '比例
'初始化匹配定位消耗时间
d_match_time = 0
d_use_imgfile = 1 '默认使用本地图片
d_index = 0
END SUB
5.关联HMI界面控件变量。
6.在“main.bas”文件中添加HMI界面初始化函数并在Hmi系统设置中关联初始化函数。
'HMI界面初始化函数,上电执行一次
GLOBAL SUB hmi_init()
ZV_ENVINIT()
ZV_SETSYSSTR("DataDir","") '设置默认数据目录
ZV_SETSYSINT("LineWidth",6) '设置线宽为 10
grab_switch = 0 '初始化采集任务开关,不开启采集任务
main_task_state = 1 '初始化定位检测主任务状态为停止状态1
ZV_RESETCLIPSIZE(1280, 960) '根据图像分辨率设置图像区域的裁剪尺寸,此处图像分辨率为1280x960
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 2), HMI_CONTROLSIZEY(10, 2)) '设置锁存的大小
init_meas_param() '初始化测量参数
ZV_IMGGENCONST(subImg,40,30,1,0,0) '初始化模板子图像
'初始化匹配使用到的中间变量
ZVOBJECT contlist1, tsContlist1, mat_rigid1
ZVOBJECT contlist2, tsContlist2, mat_rigid2
ZV_LATCHCLEAR(0) '清空锁存通道
ZV_MATGENDATA(mat_param, 1, 7, 40) '将TABLE中1行9列40的数据生成到矩阵mat_param中
END SUB
7.在“camera.bas”文件中添加HMI界面中采集相关按钮响应的函数并关联动作函数。(说明:具体实现函数前面两篇课程内容已经有操作演示,此处不做赘述。)
8.点击[元件]→[新建窗口],新建学习模板窗口,设计窗口布局,关联变量。
9.在“draw.bas”文件中添加主界面【学习模板】按钮响应的函数并关联动作函数。
'主界面按下学习模板按钮时响应的函数
GLOBAL SUB btn_sel_loc()
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(11, 60), HMI_CONTROLSIZEY(11, 60)) '设置创建模板窗口锁存通道0的锁存大小
SET_COLOR(RGB(0,255,0)) '指定draw指令使用的颜色
ZV_LATCHCLEAR(0) '将锁存通道0清空
ZV_LATCH(grabImg, 0) '将采集图像显示到锁存通道0中
ZV_LATCH(colorSubImg, 1) '将模板图像显示到锁存通道1中
is_redraw = 0 '将绘图标志置0
d_is_rtn_loc = 0 '将返回界面标志置0
'将模板区域的图像坐标存放到起始地址为25的table数组中
TABLE(25, d_locator_roi(0), d_locator_roi(1),d_locator_roi(2),d_locator_roi(3))
ZV_POSFROMIMG(0, 2, 25, 25) '将图像坐标转换到HMI控件坐标
HMI_SHOWWINDOW(11) '弹出窗口号为11的创建模板窗口
END SUB
10.在“draw.bas”文件中添加模板区域更新绘制函数,并在学习模板界面的自定义控件上关联刷新函数名和绘图函数名。
'根据鼠标操作更新定位器的区域即学习模板的有效区域
GLOBAL SUB update_locator()
if mouse_scan(11) = 1 then '扫描鼠标按下操作
is_set_roi_m_down = 1 '鼠标按下标志置1
sr_mpos_x = table(11) '将当前鼠标按下位置的坐标赋值给变量
sr_mpos_y = table(12)
'只有按下时可以改变击中位置,获取鼠标点击位置对应的击中区域编号
hit_pos = ZV_HMIADJRECT(sr_mpos_x, sr_mpos_y, 25, -1)
is_redraw = 1 '绘图标志置1
endif
if mouse_scan(11) = -1 then '扫描鼠标松开操作
is_set_roi_m_down = 0 '鼠标按下标志置0
sr_mpos_x = table(11) '将当前鼠标松开位置的坐标赋值给变量
sr_mpos_y = table(12)
'根据区域编号调整定位器区域位置
ZV_HMIADJRECT(sr_mpos_x, sr_mpos_y, 25, hit_pos)
is_redraw = 1 '绘图标志置1
endif
'如果鼠标按下时
if (is_set_roi_m_down and MOUSE_state(11)) then
sr_mpos_x = table(11) '将当前鼠标按下位置的坐标赋值给变量
sr_mpos_y = table(12)
'根据区域编号调整定位器区域位置
ZV_HMIADJRECT(sr_mpos_x, sr_mpos_y, 25, hit_pos)
is_redraw = 1 '绘图标志置1
endif
if (1 = is_redraw) then '如果绘制标志=1
is_redraw = 0 '将绘制标志置0
'控件roi坐标转图像roi坐标,控件坐标存放在起始地址为25的数组,图像坐标存放在起始地址为15的数组
ZV_POSTOIMG(0, 2, 25, 15)
'将图像坐标的数据赋值给ROI变量中
d_locator_roi(0) = TABLE(15)
d_locator_roi(1) = TABLE(16)
d_locator_roi(2) = TABLE(17)
d_locator_roi(3) = TABLE(18)
SET_REDRAW '重新绘制全部区域
endif
END SUB
11.在“main.bas”文件中添加【截取模板】按钮响应的函数并关联动作函数。
'创建模板界面按下截取模板按钮后响应的函数
GLOBAL SUB btn_getSubImg()
LOCAL mod_w,mod_h
'根据ROI数据生成模板子图像
ZV_IMGGETSUB(grabImg, subImg, d_locator_roi(0), d_locator_roi(1), d_locator_roi(2)-d_locator_roi(0)+1, d_locator_roi(3)-d_locator_roi(1)+1)
'获取图像信息,存放到起始地址为0的table数组中
ZV_IMGINFO(subImg,0)
mod_w = TABLE(0)
mod_h = TABLE(1)
'根据图像信息生成模板区域
ZV_REGENRECT(modRe,0,0,mod_w, mod_h)
'清空锁存通道1
ZV_LATCHCLEAR(1)
'将模板子图像显示到锁存通道1中
ZV_LATCH(subImg, 1)
END SUB
12.点击[元件]→[新建窗口],新建编辑模板窗口,设计窗口布局,并关联变量。
13.在“draw.bas”文件中添加创建模板界面【橡皮擦】按钮响应的函数并关联动作函数。
'创建模板界面按下橡皮擦按钮时响应的函数
GLOBAL SUB btn_sel_erase()
ZV_LATCHSETSIZE(1, HMI_CONTROLSIZEX(12, 1), HMI_CONTROLSIZEY(12, 1)) '设置锁存通道1的大小
SET_COLOR(RGB(0,255,0)) '设置绘制时画笔使用的颜色
ZV_LATCHCLEAR(1) '清空锁存通道1
ZV_IMGCOPY(subImg, copy_subImg) '复制模板子图像到copy_subImg图像变量中
ZV_REGION(copy_subImg, modRe, 1, 0) '在模板图像上绘制modRe图像的非有效区域,绘制颜色为黑色,用于掩模
ZV_LATCH(copy_subImg, 1) '显示复制的模板图
HMI_SHOWWINDOW(12) '打开编辑模板窗口
END SUB
14.在“draw.bas”文件中添加橡皮擦更新绘制函数,并在编辑模板界面的自定义控件上关联刷新函数名和绘图函数名。
'根据鼠标操作更新橡皮擦擦除/恢复区域的位置
GLOBAL SUB update_eraser()
DIM c_size_eraser '橡皮擦在控件上对应的尺寸
DIM eraser_pos_x,eraser_pos_y
d_mouse_s = MOUSE_STATE(11) '鼠标处于按下状态时
eraser_pos_x = TABLE(11) '将当前鼠标按下位置的坐标赋值给橡皮擦控件坐标变量
eraser_pos_y = TABLE(12)
c_size_eraser = ZV_LENFROMIMG(0, d_eraser_size) '将橡皮擦的图像尺寸转换成控件尺寸
'生成以(eraser_pos_x,eraser_pos_y)为中心,2*c_size_eraser为边长的正方形橡皮擦区域
c_rect(0, eraser_pos_x - c_size_eraser, eraser_pos_y - c_size_eraser, eraser_pos_x + c_size_eraser, eraser_pos_y + c_size_eraser)
DIM hmi_w,hmi_h
'限制橡皮擦坐标在图片元件区域内
if (eraser_pos_x >= c_size_eraser) and (eraser_pos_y >= c_size_eraser) and (eraser_pos_x <= HMI_CONTROLSIZEX(12, 1) - c_size_eraser)and (eraser_pos_y <= HMI_CONTROLSIZEy(12, 1) - c_size_eraser) THEN
'重新绘制编辑模板窗口上的锁存通道0区域
SET_REDRAW(0,0, HMI_CONTROLSIZEX(12, 1), HMI_CONTROLSIZEY(12, 1))
endif
if d_mouse_s = 1 and d_edit_m = 1 then '如果鼠标处于按下状态且编辑模板标志=1时
btn_pro_eraser() '执行处理橡皮擦函数
endif
END SUB
'处理橡皮擦函数
GLOBAL SUB btn_pro_eraser()
ZVOBJECT tmp_re
'将橡皮擦区域的左上角坐标x,y存放到起始地址为30的数组中
TABLE(30, c_rect(0), c_rect(1))
'将控件坐标转换到图像坐标中
ZV_POSTOIMG(1, 1, 30, 30)
'根据图像坐标系下的数据生成正方形橡皮擦区域,并存放到tmp_re变量中
ZV_REGENRECT(tmp_re, TABLE(30), TABLE(31), 2 * d_eraser_size + 1, 2 * d_eraser_size + 1)
if (d_isMask_m = 1) then '如果选择屏蔽功能
ZV_REDIFF(modRe, tmp_re, modRe) '计算modRe和tmp_re的差集并存放到modRe中,即取橡皮擦区域以外的模板子图像区域
else '如果选择恢复功能
ZV_REUNION(modRe, tmp_re, modRe) '计算modRe和tmp_re的并集并存放到modRe中,即取当前模板子图像区域
endif
ZV_IMGCOPY(subImg, copy_subImg) '复制模板子图像到copy_subImg图像变量中
ZV_REGION(copy_subImg, modRe, 1, 0) '在模板图像上绘制modRe图像的非有效区域,绘制颜色为黑色,用于掩模
ZV_LATCH(copy_subImg, 1) '显示复制的模板图
END SUB
'更新绘制橡皮擦区域
GLOBAL SUB draw_eraser()
if d_edit_m = 0 then '如果编辑模板标志为0
return '返回子函数,不继续往下执行
endif
'绘制正方形橡皮擦区域
DRAWRECT(c_rect(0), c_rect(1), c_rect(2), c_rect(3))
END SUB
15.在“main.bas”文件中添加编辑模板界面【创建模板】按钮响应的函数并关联动作函数。
'编辑模板界面按下创建模板按钮时响应的函数
GLOBAL SUB btn_loc_creModel()
d_is_creModel = 1 '创建模板标志置1
'根据模板参数和模板子图像创建模板,并将模板结果存放到s_mod变量中
ZV_SHAPECREATERE(subImg, modRe,s_mod, d_mod_param(0), d_mod_param(1), d_mod_param(2), d_mod_param(3), d_mod_param(4), d_mod_param(5), d_mod_param(6), d_mod_param(7), d_mod_param(8))
ZV_SHAPECONTOURS(s_mod, contlist1, 0) '获取第0层金字塔上的模板轮廓
ZV_GRAYTORGB(subImg, colorSubImg) '灰度图转换成RGB图
ZV_IMGINFO(colorSubImg, 0) '获取colorSubImg图像信息,并存放到table0中
ZV_GETRIGIDVECTOR(mat_rigid1, 0, 0, 0, TABLE(0)/2, TABLE(1)/2, 0)'计算刚性变换矩阵
ZV_CONTAFFINE(contlist1, mat_rigid1, tsContlist1)'对轮廓或轮廓序列进行仿射变换
ZV_CONTLIST(colorSubImg, tsContlist1, ZV_COLOR(0, 255, 0), 0)'在colorSubImg图像上绘制绿色的轮廓序列
ZV_LATCHCLEAR(2) '清空锁存通道2
ZV_LATCH(colorSubImg, 2) '显示图像结果到锁存通道2中
END SUB
16.在“main.bas”文件中添加编辑模板界面【添加模板】按钮响应的函数并关联动作函数。
'编辑模板界面按下添加模板按钮时响应的函数
GLOBAL SUB btn_loc_addModel()
DIM count
if d_is_creModel = 1 then
zv_listinsert(s_mod, modList)
count = ZV_LISTCOUNT(modList) '获取列表中的数量
ShowString="已添加模板"+TOSTR(count)
?ShowString
endif
END SUB
17.在“main.bas”文件中添加编辑模板界面【清空模板】按钮响应的函数并关联动作函数。
'编辑模板界面按下清空模板列表按钮时响应的函数
GLOBAL SUB btn_loc_clrMods()
ZV_CLEAR(modList)
?"已清空模板列表!"
END SUB
18.在“draw.bas”文件中添加编辑模板界面【确定】按钮响应的函数并关联动作函数。
'编辑模板界面按下确定按钮时执行的函数
GLOBAL SUB btn_erase_cfm()
ZV_LATCHCLEAR(0) '清空锁存通道0
ZV_LATCH(grabImg, 0) '显示图像在锁存通道0上
HMI_CLOSEWINDOW(12) '关闭编辑模板窗口
END SUB
19.在“main.bas”文件中添加创建模板界面【测试】按钮响应的函数并关联动作函数。
'创建模板界面按下测试按钮时响应的函数
GLOBAL SUB btn_loc_test()
if (d_is_creModel = 0 OR ZV_LISTCOUNT(modList)=0 ) then
?"未创建模板!" '提示未创建模板毛病返回子函数不往下执行
return
endif
'开始匹配
TICKS = 0 '开始计时
ZVOBJECT match_rst, sImg, colorImg,contours
ZV_CLEAR(match_rst)
ZV_MATINFO(match_rst, 0) '获取矩阵结果信息。并存放到起始地址为0的table数组中
'对图像进行3*3高斯平滑处理,处理后的图像输出到sImg变量中
ZV_GAUSSBLUR(grabImg, sImg, 3)
ZV_SHAPEFINDS(modlist,mat_param,sImg,match_rst,3,0)'多目标匹配
ZV_MATINFO(match_rst, 0) '获取矩阵结果信息。并存放到起始地址为0的table数组中
ZV_GRAYTORGB(sImg, colorImg) '灰度图转换到RGB图,作为匹配结果图像
if TABLE(0) > 0 then '如果匹配到目标
local rowr
for rowr = 0 to TABLE(0)-1
'获取match_rst矩阵中第rowr行的数据存放到起始地址为53的table数组中,table最大长度6
ZV_MATGETROW(match_rst, rowr, 6, 53)
zv_listget(modList, s_mod, table(58))
ZV_SHAPECONTOURS(s_mod, contours, 0)'获取模板轮廓
ZV_GETRIGIDVECTOR(mat_rigid1, 0, 0, 0, TABLE(54), TABLE(55), TABLE(56))
ZV_CONTAFFINE(contours, mat_rigid1, contours)
ZV_CONTLIST(colorImg, contours, C_GREEN, 0)
if TABLE(58)=0 then
ShowString="target1:"
elseif TABLE(58)=1 then
ShowString="target2:"
else
ShowString="target3:"
endif
ShowString1=TOSTR(TABLE(54),1,2)+","+TOSTR(TABLE(55),1,2)+","+TOSTR(TABLE(56),1,2)
TABLE(54)=TABLE(54)-40
ZV_TEXT(colorImg,ShowString,TABLE(54), TABLE(55),50,ZV_COLOR(255,0,255) )
TABLE(55)=TABLE(55)+50
ZV_TEXT(colorImg,ShowString1,TABLE(54), TABLE(55),50,ZV_COLOR(255,0,255) )
next
else '未匹配到目标时,将结果赋值为-1
d_match_rst(0) = -1
d_match_rst(1) = -1
d_match_rst(2) = -1
d_match_rst(3) = -1
d_match_rst(4) = -1
endif
d_match_time = abs(TICKS) '计算匹配消耗时间
ZV_LATCH(colorImg, 0) '显示匹配结果图像
END SUB
20.在“draw.bas”文件中添加创建模板界面【确定】按钮响应的函数并关联动作函数。
'创建模板界面按下确定按钮时响应的函数
GLOBAL SUB btn_loc_cfm()
grab_switch = 0 '关闭补正源的连续采集
d_is_rtn_loc = 1 '返回主界面标志置为1
'设置锁存通道0的大小
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 2), HMI_CONTROLSIZEY(10, 2))
ZV_LATCHCLEAR(0) '清空锁存通道0
ZV_LATCH(grabImg, 0) '显示图像在锁存通道0上
HMI_CLOSEWINDOW(11) '关闭创建模板窗口
END SUB
21.在“main.bas”文件中添加主界面【单次执行】按钮响应的函数并关联动作函数。
'主界面按下单次执行按钮时响应的函数
GLOBAL SUB btn_test()
'执行单次采集响应函数获取一帧图像
btn_grab()
'执行测试按钮响应函数进行匹配定位检测
btn_loc_test()
END SUB
22.在“main.bas”文件中添加主界面【连续运行】按钮响应的函数并关联动作函数。
'主界面点击连续运行按钮时响应的函数
GLOBAL SUB btn_run()
if(run_switch = 1) then '如果已经开启连续运行
?"已开启连续运行,请勿重复操作!" '提示信息并退出子函数,不往下执行
return
endif
run_switch = 1 '主任务开关置1
if (1 = run_switch) then '如果主任务开关=1
if (0 = PROC_STATUS(main_task_id)) then '如果main_task_id任务未开启
RUNTASK main_task_id, main_task '开启main_task任务
endif
endif
END SUB
'主任务执行的内容
main_task:
while(1)
if (0 = run_switch) then '如果主任务开关=0即停止运行按钮按下时
exit while '退出循环
endif
'否则重复执行以下操作
if (d_use_imgfile=1) then '如果d_use_imgfile=1时使用读取本地图片功能
if(d_index=3) then
d_index=0
endif
File_Name="多轮廓/"+TOSTR(d_index,1,0)+".bmp" '读取本地图片时图片所在的路径名称
ZV_IMGREAD(grabImg,File_Name,0)
d_index=d_index+1
else
'如果相机数量为0,提示先扫描相机,并退出子函数不往下执行
if cam_num = 0 then
?"请先扫描相机!"
return
endif
CAM_SETPARAM("TriggerSoftware", 0) '发送触发指令
CAM_GET(grabImg, 0)
endif
'执行测试按钮响应函数进行匹配定位检测
btn_loc_test()
wend
END
23.在“main.bas”文件中添加主界面【停止运行】按钮响应的函数并关联动作函数。
'主界面点击停止执行按钮时响应的函数
GLOBAL SUB btn_stop()
if(run_switch = 0) then '如果主任务开关=0
?"未开启连续运行!" '提示未开启循环任务,并退出子函数不往下执行
return
endif
run_switch = 0 '主任务开关置0,退出循环
END SUB
三 操作演示
(一)操作步骤
查看运行效果:将项目下载到仿真器中→使用本地图片→单次采集→学习模板→截取模板→橡皮檫依次创建所需的几个模板→依次添加几个模板→点击测试查看效果图,再点击确定返回主界面。→点击连续运行,查看运行效果→结束。
(二)效果演示