机器视觉运动控制一体机应用例程(十)工件圆度检测

现有的测量工件圆度的方法一般是采用圆度测量仪,其是利用回转轴法测量圆度的长度测量工具。圆度仪分为传感器回转式和工作台回转式两种检测方法。
检测圆度时,样品需要与精密轴系同心安装,精密轴系带着电感式长度传感器或工作台作精确的圆周运动。
由仪器的传感器、放大器、滤波器等配合使用输出后再计算结果。采用该方法不仅耗时耗力、且成本较高、操作难度系数高,而且难以满足大批量工件检测圆度的需要。
采用机器视觉检测圆度方法获得的数据检测结果,不仅检测速度快,且成本较低,适合大批量工件检测圆度的需要以及提高其生产产能。
但是由于目前采用机器视觉测量对于数据的处理会因为工件图像边缘模糊影响测量精度,所以正运动技术本次采用新的数据处理方法,以此来提高检测圆度的精度和检测速度,此方案可以满足客户大批量工件检测圆度的需求。
上期课程,我们讲述了机器视觉方案中线束颜色排序识别的应用例程,本期课程我们将和大家一起分享如何实现工件检测圆度的功能。
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_statemain_task_state = 1
'运行任务开关GLOBAL DIM run_switchrun_switch = 0
'采集任务开关'0 - 停止采集'1 - 请求采集GLOBAL DIM grab_switchgrab_switch = 0
'定位检测主任务id - 10GLOBAL DIM main_task_idmain_task_id = 10
'相机连续采集线程id - 7GLOBAL DIM grab_task_idgrab_task_id = 7
'***********结束定义程序任务相关变量******************
'***********定义相机采集相关变量**********************
'相机种类,此处使用海康相机-'mvision'GLOBAL DIM CAMERA_TYPE(100)'CAMERA_TYPE = 'mindvision;basler;mvision;huaray;zmotion'CAMERA_TYPE = 'mvision'
'相机个数GLOBAL cam_numcam_num = 0
'相机模式,-1 连续采集,0-软件触发采集GLOBAL cam_modecam_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_downis_set_roi_m_down = 0
GLOBAL DIM d_detect_time '定义消耗的时间变量d_detect_time = 0
'定义程序执行过程中采集的图像变量、二值化图像变量、显示图像变量、提取到的轮廓列表GLOBAL ZVOBJECT grabImg,binImg,colorImg,contlist
'定义最小轮廓长度GLOBAL DIM minLengthminLength=1700 '默认提取轮廓最小长度为600像素
'定义提取到轮廓的数量GLOBAL DIM countcount=0
'定义保存参数标志GLOBAL DIM d_is_saved
'定义提取轮廓的ROI区域GLOBAL DIM d_learn_roi(4)d_learn_roi(0)=180d_learn_roi(1)=110d_learn_roi(2)=380d_learn_roi(3)=310TABLE(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_YELLOWC_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)=0d_detect_param(1)=128d_detect_param(2)=255d_detect_param(3)=0.99
'定义检测状态结果,0-NG,1-OKGLOBAL DIM result_status
'***********定义读取本地文件功能相关变量**************''注意,该功能只在使用仿真器时有效'定义是否使用本地图片标志GLOBAL DIM d_use_imgfiled_use_imgfile=1
'定义本地图片索引GLOBAL DIM d_index
'定义读取图片的路径GLOBAL DIM File_Name(100)
'***********结束定义读取本地文件功能相关变量**********
'初始化全局变量完成后开启HMI文件RUN'Hmi1.hmi',14.关联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()endifZV_RESETCLIPSIZE(2592, 1944)'初始化时依据图像分辨率设置区域的裁剪尺寸,此处图像分辨率为2592x1944ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 1), HMI_CONTROLSIZEY(10, 1)) '设置锁存的大小ZV_SETSYSDBL('CamGetTimeout', 1000) '设置采集超时ZV_LATCHCLEAR(0) '清空锁存通道0END 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_redrawis_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=0result_status=0ZVOBJECT regionMask,contour,genList,fragment,regionWhite,conl_matrix,repolyLOCAL width,heigthzv_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 '如果选择手动阈值模式'根据低阈值和高阈值参数生成白色像素图像regionWhiteZV_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图像中的指定区域内对图像进行自动二值化处理,输出二值化区域regionWhiteZV_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 '打印提示信息,当前二值化阈值endifZV_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-1ZV_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=1endifnextZV_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 '如果已经开启连续运行?'已开启连续运行,请勿重复操作!' '提示信息并退出子函数,不往下执行returnendifrun_switch = 1 '主任务开关置1if (1 = run_switch) then '如果主任务开关=1if (0 = PROC_STATUS(main_task_id)) then '如果main_task_id任务未开启RUNTASK main_task_id, main_task '开启main_task任务endifendifEND SUB'主任务执行的内容main_task:while(1)if (0 = run_switch) then '如果主任务开关=0即停止运行按钮按下时exit while '退出循环endif'否则重复执行以下操作if (d_use_imgfile=1) thenif(d_index=4) thend_index=0endifFile_Name='检测圆度/'+TOSTR(d_index,1,0)+'.bmp' '.../flash/3/目录下的图片所在的路径名称ZV_IMGREAD(grabImg,File_Name,1)d_index=d_index+1elseif cam_num = 0 then?'请先扫描相机!'returnendifCAM_SETPARAM('TriggerSoftware', 0) '发送触发指令CAM_GET(grabImg, 0) '获取一帧图像存放到grabImg变量中endif'执行提取轮廓子程序btn_test()wendEND

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
本次,正运动技术机器视觉运动控制一体机应用例程(十)工件圆度检测,就分享到这里。
