机器视觉运动控制一体机应用例程(六)液位检测
顺应现代生活的不断发展,瓶装液体成为人们日常生活中不可或缺的消费品。它的包装中产品净含量是否达标是检测产品质量的一个重要指标,对于同一规格的包装瓶中,其液位高度直接反映了瓶中液体的净含量。
在传统的瓶装液体灌装工序中,其灌装后的液位高度检测通常采用的是人眼去目测液位高度,生产效率低下,且会产生较大误差。随着生产的规模的不断扩大,因此对瓶装液体的液位高度全自动检测的需求越来越大。
目前市面上已有光电传感器检测、超声波检测和机器视觉液位检测等液位检测方法,其中机器视觉液位检测是一种非接触式、无损的检测方法。因此它具有效率高、检测精度高、设备维护简单等优点,被广泛应用于液位检测项目中。
本次课程我们将与大家一起分享机器视觉运动控制一体机实现液位检测的功能。
16:11
液位检测:在机器视觉解决方案中,通常使用背向打光的方式将瓶内有液体的部分和没有液体的部分加以区分,再计算出液体最高位与瓶底的距离即液位。检测有颜色的液体通常使用普通背光源即可,如需检测透明液体或瓶子上有字符或颜色干扰可使用穿透性较强的红外背光。
视觉算法:使用两个直线测量器获得瓶底和液位的数据,再计算瓶底和液位的距离。使用形状匹配结果作为直线测量器的补正源,使直线测量器跟随产品移动。
(一)软件实现
1.打开ZDevelop软件:打开项目“基于形状匹配的视觉定位”→在“global_variable.bas”文件中定义测量尺寸需要用到的全局变量。
'----------------------------分割线-----------------------------------------
'直线1测量参数数组,依次为中心cx、cy、w、h、angle、interp、sub_num、sub_width、filter_size、thresh、polor、select,都是图像坐标
GLOBAL DIM d_meas_param1(12) 'd开头表示数据结构
'直线2测量参数数组,依次为中心cx、cy、w、h、angle、interp、sub_num、sub_width、filter_size、thresh、polor、select,都是图像坐标
GLOBAL DIM d_meas_param2(12) 'd开头表示数据结构
'定义常用颜色变量,用于绘制图形
GLOBAL C_RED, C_GREEN, C_BLUE, C_YELLOW
C_RED = RGB(255, 0, 0)
C_GREEN = RGB( 0,255, 0)
C_BLUE = RGB( 0, 0,255)
C_YELLOW= RGB(255,255, 0)
'创建模板时保存的直线1基准区域位置向量1,x、y、angle
GLOBAL DIM d_meas_base_v1(3)
d_meas_base_v1(0) = 0
d_meas_base_v1(1) = 0
d_meas_base_v1(2) = 0
'创建模板时保存的直线2基准区域位置向量2,x、y、angle
GLOBAL DIM d_meas_base_v2(3)
d_meas_base_v2(0) = 0
d_meas_base_v2(1) = 0
d_meas_base_v2(2) = 0
'直线1测量结果,依次为结果点stx、sty、endx、endy
GLOBAL DIM d_meas_rst1(4)
'直线2测量结果,依次为结果点stx、sty、endx、endy
GLOBAL DIM d_meas_rst2(4)
''创建模板时保存的模板基准点,score、x、y、angle、scale
GLOBAL DIM d_match_base_rst(5)
global dim d_meas_param(12)
'定义ROI标志变量,0-液位ROI,1-瓶底ROI
GLOBAL DIM roi_flag
roi_flag=0
'定义形状匹配模板
ZVOBJECT shape_model
'定义保存配模板标志,1-已保存,0未保存
GLOBAL DIM is_saveMod
2.修改设计HMI界面。
3.新建主界面按下【液位设置】按钮时弹出的液位参数设置窗口“Set_Select”,并设计界面布局。
4.关联液位参数设置窗口“Set_Select”界面上的变量。
5.在“draw.bas”文件中添加“液位Roi”和“瓶底Roi”根据鼠标操作更新ROI位置的函数以及实时绘制Roi的函数,并在自定义元件中关联刷新函数和绘制函数。
'-----------------分割线-------------------------
'测量器绘制
'''''''''''''''''''''''''''''''''''
'根据鼠标操作更新Roi的位置
GLOBAL SUB update_roi()
if roi_flag=0 then '如果选择设置液位ROI
SET_REDRAW'全区域绘制
if (mouse_scan(21) = 1 )then '如果扫描到鼠标按下操作
'根据鼠标所在Roi的不同位置返回调整标志
hit_pos = ZV_HMIADJRECT2(table(21), table(22), 11, -1)
is_redraw = 1'绘图标志置1
endif
if mouse_scan(21) = -1 then '如果扫描到鼠标松开操作
'如果鼠标指在Roi1区域之外
if TABLE(21)<(TABLE(11)-TABLE(13)/2) or TABLE(21)>(TABLE(11)+TABLE(13)/2) or TABLE(22)<(TABLE(12)-TABLE(14)/2)or TABLE(22)>(TABLE(12)+TABLE(14)/2) then
hit_pos=-1'调整标志=-1
endif
ZV_HMIADJRECT2(table(21), table(22), 11, hit_pos)'调整Roi1位置
is_redraw = 1
endif
if (MOUSE_state(21)) then'如果鼠标按下时
ZV_HMIADJRECT2(table(21), table(22), 11, hit_pos)'调整Roi1位置
is_redraw = 1'绘图标志置1
endif
if (1 = is_redraw ) then'如果绘图标志为1时
is_redraw = 0'绘图标志置0
'将控件坐标转换到图像坐标,并赋值给相应变量
ZV_POSTOIMG(0, 1, 11, 31)
d_meas_param1(0) = TABLE(31)
d_meas_param1(1) = TABLE(32)
d_meas_param1(2) = ZV_LENTOIMG(0, TABLE(13))
d_meas_param1(3) = ZV_LENTOIMG(0, TABLE(14))
d_meas_param1(4) = TABLE(15)
set_base_roi()'设置基准Roi数据
SET_REDRAW'全区域绘制
endif
else '否则选择设置瓶底ROI
SET_REDRAW'全区域绘制
if (mouse_scan(21) = 1 )then '如果扫描到鼠标按下操作
'根据鼠标所在Roi的不同位置返回调整标志
hit_pos = ZV_HMIADJRECT2(table(21), table(22), 41, -1)
is_redraw = 1'绘图标志置1
endif
if mouse_scan(21) = -1 then '如果扫描到鼠标松开操作
'如果鼠标指在Roi2区域之外
if TABLE(21)<(TABLE(41)-TABLE(43)/2) or TABLE(21)>(TABLE(41)+TABLE(43)/2) or TABLE(22)<(TABLE(42)-TABLE(44)/2)or TABLE(22)>(TABLE(12)+TABLE(14)/2) then
hit_pos=-1'调整标志=-1
endif
ZV_HMIADJRECT2(table(21), table(22), 41, hit_pos)'调整Roi2位置
is_redraw = 1
endif
if (MOUSE_state(21)) then'如果鼠标按下时
ZV_HMIADJRECT2(table(21), table(22), 41, hit_pos)'调整Roi2位置
is_redraw = 1'绘图标志置1
endif
if (1 = is_redraw ) then'如果绘图标志为1时
is_redraw = 0'绘图标志置0
'将控件坐标转换到图像坐标,并赋值给相应变量
ZV_POSTOIMG(0, 1, 41, 91)
d_meas_param2(0) = TABLE(91)
d_meas_param2(1) = TABLE(92)
d_meas_param2(2) = ZV_LENTOIMG(0, TABLE(43))
d_meas_param2(3) = ZV_LENTOIMG(0, TABLE(44))
d_meas_param2(4) = TABLE(45)
set_base_roi()'设置基准Roi数据
SET_REDRAW'全区域绘制
endif
endif
END SUB
6.在“main.bas”文件中添加“Set_Select”窗口界面按下【测试】按钮时响应的函数并关联动作函数名。
'液位设置界面按下测试按钮时响应的函数
GLOBAL SUB btn_mea_test()
'选择补正源时先执行定位检测
if(TABLE(110) = 1) then
btn_loc_test()
endif
ZVOBJECT mr1,mr2,mr3,mr4,rst1,rst2,rst3,rst4,colorImg
ZVOBJECT contlist, tsContlist, mat_rigid
LOCAL show_rst
'测量区域roi补正
if(TABLE(110) = 1 AND d_is_creModel = 1) then '如果使用补正源已经开启且模板已经创建
'计算刚性变换矩阵
ZV_GETRIGIDVECTOR(mat_rigid1,d_match_base_rst(1),d_match_base_rst(2),d_match_base_rst(3), d_match_rst(1), d_match_rst(2), d_match_rst(3))
'使用变换矩阵mat_rigid对输入Roi1基准向量进行补正,补正后的向量存入开始索引为0的TABLE中
ZV_VECTORCORRECT(mat_rigid1, d_meas_base_v1(0), d_meas_base_v1(1),d_meas_base_v1(2), 0)
'将补正后的坐标数据赋值给测量器区域变量
d_meas_param1(0) = TABLE(0)
d_meas_param1(1) = TABLE(1)
d_meas_param1(4) = TABLE(2)
'使用变换矩阵mat_rigid对输入Roi2基准向量进行补正,补正后的向量存入开始索引为0的TABLE中
ZV_VECTORCORRECT(mat_rigid1, d_meas_base_v2(0), d_meas_base_v2(1),d_meas_base_v2(2), 0)
'将补正后的坐标数据赋值给测量器区域变量
d_meas_param2(0) = TABLE(0)
d_meas_param2(1) = TABLE(1)
d_meas_param2(4) = TABLE(2)
endif
'生成直线1测量的旋转区域
ZV_MRGENLINE(mr1, d_meas_param1(0), d_meas_param1(1), d_meas_param1(2), d_meas_param1(3), d_meas_param1(4), 1, d_meas_param1(6), d_meas_param1(7))
'设置直线1的检测参数,包括滤波器尺寸,阈值,边缘极性,边缘位置
ZV_MRSETADV(mr1, d_meas_param1(8), d_meas_param1(9), d_meas_param1(10), d_meas_param1(11))
'生成直线2测量的旋转区域
ZV_MRGENLINE(mr2, d_meas_param2(0), d_meas_param2(1), d_meas_param2(2), d_meas_param2(3), d_meas_param2(4), 1, d_meas_param2(6), d_meas_param2(7))
'设置直线2的检测参数,包括滤波器尺寸,阈值,边缘极性,边缘位置
ZV_MRSETADV(mr2, d_meas_param2(8), d_meas_param2(9), d_meas_param2(10), d_meas_param2(11))
'将矩形测量区域测量到的目标直线1端点存储到起始索引为61的TABLE
ZV_MRLINE(mr1, grabImg, rst1, 61)
'将直线1结果赋值给直线1结果变量
d_meas_rst1(0) = TABLE(61)
d_meas_rst1(1) = TABLE(62)
d_meas_rst1(2) = TABLE(63)
d_meas_rst1(3) = TABLE(64)
'将矩形测量区域测量到的目标直线2端点存储到起始索引为71的TABLE
ZV_MRLINE(mr2, grabImg, rst2, 71)
'将直线1结果赋值给直线2结果变量
d_meas_rst2(0) = TABLE(71)
d_meas_rst2(1) = TABLE(72)
d_meas_rst2(2) = TABLE(73)
d_meas_rst2(3) = TABLE(74)
'计算两条直线的距离宽度
length1()
'将灰度图转换成RGB图像,用于绘制检测结果图像
ZV_GRAYTORGB(grabImg, colorImg)
'绘制液位检测和瓶底检测的测量器
ZV_MEASURER(colorImg,mr1,ZV_COLOR(0,0,255),ZV_COLOR (0,255,0))
ZV_MEASURER(colorImg,mr2,ZV_COLOR(0,0,255),ZV_COLOR (0,255,0))
'绘制直线结果
ZV_LINE(colorImg, TABLE(61), TABLE(62), TABLE(63), TABLE(64), C_BLUE)
ZV_LINE(colorImg, TABLE(71), TABLE(72), TABLE(73), TABLE(74), C_BLUE)
if(TABLE(110) = 1) then'如果使用补正源
ZV_MARKER(colorImg,TABLE(4),TABLE(5),0,10,C_GREEN)'绘制匹配中心标志点
endif
ZV_LATCH(colorImg,0)'显示结果图像
END SUB
7.在“main.bas”文件中添加“Set_Select”窗口界面按下【返回主界面】按钮时响应的函数并关联动作函数名。
'按下返回主界面按钮时响应的函数
GLOBAL SUB Goto_Main()
'设置锁存通道0的大小,以适应图片元件大小
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10,2), HMI_CONTROLSIZEY(10,2))
ZV_LATCHCLEAR(0)'清空锁存通道0
ZV_LATCH(grabImg,0)'将图片显示到锁存通道0中
HMI_CLOSEWINDOW(13)'关闭测量参数设置窗口
END SUB
8.在“main.bas”文件中修改主界面按下【单次执行】按钮时响应的函数并关联动作函数名。
'主界面按下单次执行按钮时响应的函数
GLOBAL SUB btn_test()
'采集一帧图像
btn_grab
'执行测量测试部分代码
btn_mea_test()
END SUB
(一)操作步骤
查看运行效果:将项目下载到仿真器中→运行程序,测试程序运行效果。→使用本地图片→单次采集→学习模板→液位设置→使用补正源→单次执行→结束