机器视觉运动控制一体机应用例程(十)工件圆度检测
现有的测量工件圆度的方法一般是采用圆度测量仪,其是利用回转轴法测量圆度的长度测量工具。圆度仪分为传感器回转式和工作台回转式两种检测方法。
检测圆度时,样品需要与精密轴系同心安装,精密轴系带着电感式长度传感器或工作台作精确的圆周运动。
由仪器的传感器、放大器、滤波器等配合使用输出后再计算结果。采用该方法不仅耗时耗力、且成本较高、操作难度系数高,而且难以满足大批量工件检测圆度的需要。
采用机器视觉检测圆度方法获得的数据检测结果,不仅检测速度快,且成本较低,适合大批量工件检测圆度的需要以及提高其生产产能。
但是由于目前采用机器视觉测量对于数据的处理会因为工件图像边缘模糊影响测量精度,所以正运动技术本次采用新的数据处理方法,以此来提高检测圆度的精度和检测速度,此方案可以满足客户大批量工件检测圆度的需求。
上期课程,我们讲述了机器视觉方案中线束颜色排序识别的应用例程,本期课程我们将和大家一起分享如何实现工件检测圆度的功能。
14:29
(一)检测需求
检测圆环状产品的内外圆轮廓有无变形。
(二)软件算法
先将灰度图像进行二值化处理成二值图像后再提取出圆环产品上的内外圆轮廓,然后用计算轮廓圆度的指令输出轮廓的圆度值,小于一定值判定该产品轮廓已变形。
(一)软件实现
1.打开ZDevelop软件:新建名称为“Contour.zpj”项目→新建“HMI文件”→新建“main.bas”文件,用于编写界面响应函数→新建“global_variable.bas”文件用于存放全局变量并开启HMI自动运行任务→新建“draw.bas”文件用于更新绘制ROI数据→新建“camera.bas”文件用于实现相机采集功能→文件添加到项目。
2.设计HMI界面。
3.在“global_variable.bas”文件中定义全局变量,定义完成后运行“Hmi.hmi”文件。
'''''全局变量大部分使用数组结构'''''
''注:basic编程中很多函数会以TABLE(系统的数据结构)做为参数
''table 说明 table 说明
''11~12 鼠标操作时获取的坐标 15~18 提取轮廓ROI图像坐标数据
''25~28 提取轮廓ROI控件坐标数据 40 轮廓点数量
''50~50+轮廓数量*2 指定轮廓的轮廓点坐标
''vr 说明 vr 说明
''0 轮廓最小长度 1 选择ROI类型
''2~5 ROI图像坐标数据 6 选择相机采集/本地图像
''7 数据保存标志 9~12 ROI控件坐标数据
'***********定义程序任务相关变量**********************
'主任务状态
'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
'***********结束定义相机采集相关变量******************
'定义使用ROI标志,1-使用ROI,0-使用全图像区域
GLOBAL DIM d_roi_arc_flag
d_roi_arc_flag = 0
'定义鼠标按下标志位,1-已按下,0-未按下
GLOBAL DIM is_set_roi_m_down
is_set_roi_m_down = 0
GLOBAL DIM d_detect_time '定义消耗的时间变量
d_detect_time = 0
'定义程序执行过程中采集的图像变量、二值化图像变量、显示图像变量、提取到的轮廓列表
GLOBAL ZVOBJECT grabImg,binImg,colorImg,contlist
'定义最小轮廓长度
GLOBAL DIM minLength
minLength=1700 '默认提取轮廓最小长度为600像素
'定义提取到轮廓的数量
GLOBAL DIM count
count=0
'定义保存参数标志
GLOBAL DIM d_is_saved
'定义提取轮廓的ROI区域
GLOBAL DIM d_learn_roi(4)
d_learn_roi(0)=180
d_learn_roi(1)=110
d_learn_roi(2)=380
d_learn_roi(3)=310
TABLE(25) = d_learn_roi(0) '将矩形ROI数据存放到起始地址为25的table数组中
TABLE(26) = d_learn_roi(1)
TABLE(27) = d_learn_roi(2)
TABLE(28) = d_learn_roi(3)
'常用颜色变量
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)
'检测参数:阈值模式(自动阈值或手动阈值)、低阈值、高阈值、圆度下限
GLOBAL DIM d_detect_param(4) 'd开头表示数据结构
d_detect_param(0)=0
d_detect_param(1)=128
d_detect_param(2)=255
d_detect_param(3)=0.99
'定义检测状态结果,0-NG,1-OK
GLOBAL DIM result_status
'***********定义读取本地文件功能相关变量**************
''注意,该功能只在使用仿真器时有效
'定义是否使用本地图片标志
GLOBAL DIM d_use_imgfile
d_use_imgfile=1
'定义本地图片索引
GLOBAL DIM d_index
'定义读取图片的路径
GLOBAL DIM File_Name(100)
'***********结束定义读取本地文件功能相关变量**********
'初始化全局变量完成后开启HMI文件
RUN'Hmi1.hmi',1
4.关联HMI界面控件变量。
5.在“main.bas”文件中添加HMI界面初始化函数并在Hmi系统设置中关联初始化函数。
end
'注:
'凡是要使用Region有关的算子在系统初始化时都要调用ZV_RESETCLIPSIZE(width, height)这个算子设置下图像尺寸,以满足相机分辨率,因为默认的是640*480尺寸
'HMI界面初始化函数
GLOBAL SUB hmi_init()
grab_switch = 0 '停止采集
main_task_state = 1 '主任务停止运行
if(VR(7)=1)then '如果有保存参数,则加载保存的参数
btn_LoadParam()
endif
ZV_RESETCLIPSIZE(2592, 1944)'初始化时依据图像分辨率设置区域的裁剪尺寸,此处图像分辨率为2592x1944
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 1), HMI_CONTROLSIZEY(10, 1)) '设置锁存的大小
ZV_SETSYSDBL('CamGetTimeout', 1000) '设置采集超时
ZV_LATCHCLEAR(0) '清空锁存通道0
END SUB
'加载保存参数子程序
GLOBAL SUB btn_LoadParam()
'加载保存的参数
minLength=VR(0)
d_roi_arc_flag=VR(1)
d_learn_roi(0)=VR(2)
d_learn_roi(1)=VR(3)
d_learn_roi(2)=VR(4)
d_learn_roi(3)=VR(5)
d_use_imgfile =VR(6)
TABLE(25) = VR(9)
TABLE(26) = VR(10)
TABLE(27) = VR(11)
TABLE(28) = VR(12)
END SUB
6.在“draw.bas”文件中添加HMI界面自定义元件中操作绘制ROI时响应的函数并关联刷新函数和绘图函数。
end
'和绘制(即选择ROI)有关的界面的刷新绘制函数放在这个bas文件里
DIM is_redraw
is_redraw = 0
DIM hit_pos,sr_mpos_x ,sr_mpos_y
'根据鼠标操作更新绘制ROI数据的有效区域
GLOBAL SUB update_roi()
if d_roi_arc_flag = 1 then '如果选择ROI类型为矩形
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_learn_roi(0) = TABLE(15)
d_learn_roi(1) = TABLE(16)
d_learn_roi(2) = TABLE(17)
d_learn_roi(3) = TABLE(18)
SET_REDRAW '重新绘制全部区域
endif
else
SET_REDRAW
endif
END SUB
'根据更新的鼠标位置坐标绘制ROI数据区域
GLOBAL SUB draw_roi()
if d_roi_arc_flag = 1 then '如果ROI类型为矩形
SET_COLOR(C_BLUE) '设置绘制时画笔的颜色为蓝色
'根据控件坐标数据绘制矩形
DRAWRECT(TABLE(25), TABLE(26), TABLE(27), TABLE(28))
local cx,cy '定义局部变量
cx = (TABLE(25) + TABLE(27)) / 2 '计算矩形的中心坐标x、y
cy = (TABLE(26) + TABLE(28)) / 2
DRAWLINE(cx-5, cy, cx+5, cy) '绘制中心十字线
DRAWLINE(cx, cy-5, cx, cy+5)
endif
END SUB
7.在“camera.bas”文件中添加HMI界面中采集相关按钮响应的函数并关联动作函数。(说明:具体实现函数前面课程内容已经有操作演示,此处不做赘述。)
8.在“main.bas”文件中添加HMI界面中测试按钮响应的函数并关联动作函数。
'定义HMI界面按下测试按钮时响应的函数
GLOBAL SUB btn_test()
TICKS=0
result_status=0
ZVOBJECT regionMask,contour,genList,fragment,regionWhite,conl_matrix,repoly
LOCAL width,heigth
zv_imginfo(grabImg,0)'获取图像宽高
width=TABLE(0)
heigth=TABLE(1)
'生成ROI区域
if d_roi_arc_flag = 1 then '如果选择的ROI类型是矩形
'根据ROI数据生成旋转矩形区域
ZV_REGENRECT(regionMask,d_learn_roi(0),d_learn_roi(1),d_learn_roi(2)-d_learn_roi(0)+1,d_learn_roi(3)-d_learn_roi(1)+1) '生成矩形测量区域
else
'生成全图像区域
ZV_REGENFULLIMG(grabImg,regionMask)
endif
'二值化处理
if d_detect_param(0) = 0 then '如果选择手动阈值模式
'根据低阈值和高阈值参数生成白色像素图像regionWhite
ZV_RETHRESH(grabImg, regionMask, regionWhite, d_detect_param(1), d_detect_param(2))
'对白色像素区域进行一次1*1的开运算
ZV_REOPENING(regionWhite,regionWhite,1,1)
'对白色像素区域进行一次1*1的闭运算
ZV_RECLOSING(regionWhite,regionWhite,10,10)
else '如果选择自动阈值模式
Dim autoThresh '定义自动阈值模式下的二值化阈值
'在grabImg图像中的指定区域内对图像进行自动二值化处理,输出二值化区域regionWhite
ZV_REAUTOTHRESH(grabImg, regionMask, regionWhite, 0)
'对白色像素区域进行一次1*1的开运算
ZV_REOPENING(regionWhite,regionWhite,1,1)
'对白色像素区域进行一次1*1的闭运算
ZV_RECLOSING(regionWhite,regionWhite,10,10)
autoThresh = TABLE(0)
? 'autoThresh = ' autoThresh '打印提示信息,当前二值化阈值
endif
ZV_RETOIMG(regionWhite,grabImg,width,heigth) '区域转二值化图像
ZV_CLEAR(contlist)
ZV_CONTGEN(grabImg,contlist,1,1)'使用二值图像提取轮廓
ZV_CONTFILTER(contlist,4,minLength,30000,0)'过滤轮廓,保留轮廓周长在minLength和30000之间的轮廓
ZV_GRAYTORGB(grabImg,colorImg)'将灰度图转换到RGB图像,用于绘制检测结果图像
count = ZV_LISTCOUNT(contlist) '获取列表中的数量
for i=0 to count-1
ZV_LISTGET(contlist,contour,i) '获取列表中序号为i的元素
ZV_CONTTOMATRIX(contour,conl_matrix) '轮廓点集提取到矩阵中
ZV_CONTOUR(colorImg,contour,zv_color(0,255,0))
ZV_CONTCCLTY(contour,200) '计算轮廓的圆度存放于TABLE(200)
if (TABLE(200)<=d_detect_param(3)) then '如果轮廓圆度小于圆度下限值
result_status=1
endif
next
ZV_LATCH(colorImg,0)
d_detect_time=abs(TICKS)
END SUB
9.在“main.bas”文件中添加HMI界面中保存按钮响应的函数并关联动作函数。
'HMI界面按下保存按钮时响应的函数
GLOBAL SUB btn_SaveParam()
VR(0)=minLength
VR(1)=d_roi_arc_flag
VR(2)=d_learn_roi(0)
VR(3)=d_learn_roi(1)
VR(4)=d_learn_roi(2)
VR(5)=d_learn_roi(3)
VR(6)=d_use_imgfile
VR(9)=TABLE(25)
VR(10)= TABLE(26)
VR(11)=TABLE(27)
VR(12)=TABLE(28)
d_is_saved=1
VR(7)=d_is_saved
?'已成功保存参数'
END SUB
10.在“main.bas”文件中添加HMI界面中运行按钮响应的函数并关联动作函数。
'主界面点击运行按钮时响应的函数
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
if(d_index=4) then
d_index=0
endif
File_Name='检测圆度/'+TOSTR(d_index,1,0)+'.bmp' '.../flash/3/目录下的图片所在的路径名称
ZV_IMGREAD(grabImg,File_Name,1)
d_index=d_index+1
else
if cam_num = 0 then
?'请先扫描相机!'
return
endif
CAM_SETPARAM('TriggerSoftware', 0) '发送触发指令
CAM_GET(grabImg, 0) '获取一帧图像存放到grabImg变量中
endif
'执行提取轮廓子程序
btn_test()
wend
END
11.在“main.bas”文件中添加HMI界面中停止按钮响应的函数并关联动作函数。
'主界面点击停止按钮时响应的函数
GLOBAL SUB btn_stop()
if(run_switch = 0) then '如果主任务开关=0
?'未开启连续运行!' '提示未开启循环任务,并退出子函数不往下执行
return
endif
run_switch = 0 '主任务开关置0,退出循环
END SUB
(一)操作步骤
查看运行效果:将项目下载到仿真器中→使用本地图片→单次采集→选择ROI类型为全区域类型→阈值模式设置为手动阈值→阈值范围设置128~255→设置最小轮廓长度为1700→圆度下限设置为0.99→点击测试,查看检测效果→点击运行,查看连续运行效果→结束。
01:29
本次,正运动技术机器视觉运动控制一体机应用例程(十)工件圆度检测,就分享到这里。