此前,我們依次講解了軟硬件介紹及計(jì)數(shù)實(shí)例、相機(jī)的基本使用、基于形狀匹配的視覺定位、BLOB有無檢測、測量尺寸、機(jī)器視覺方案中使用到的標(biāo)定功能、ZDevelop軟件實(shí)現(xiàn)識別條形碼和二維碼,以及測量點(diǎn)/直線/圓的功能。
本期課程我們和大家一起分享機(jī)器視覺中使用到的簡單的外觀檢測功能---檢測劃痕。
一、原理
外觀檢測是機(jī)器視覺技術(shù)中一個重要的檢測功能,它可以檢測產(chǎn)品表面的臟污、瑕疵、缺陷、毛邊、劃痕等不良因素。在包裝行業(yè)和生產(chǎn)制造業(yè)被廣泛應(yīng)用。
1.劃痕檢測的原理是什么?
由于劃痕是隨機(jī)出現(xiàn)且不具有固定形態(tài)的特征,因此無法使用匹配等定位功能檢測判斷劃痕。這時就需要用到形態(tài)學(xué)處理提取劃痕特征,再配合BOLB檢測判斷劃痕有無。
劃痕檢測是使用形態(tài)學(xué)方法(如頂帽算法)將灰度圖像轉(zhuǎn)換成二值化圖像后,提取劃痕的圖像特征,再使用BLOB檢測對劃痕的特征進(jìn)行有無檢測。
2.什么是頂帽算法?
頂帽算法是將原始的圖像(逐像素)減去開運(yùn)算的圖像,得到開運(yùn)算中消除的小面積的局部亮像素區(qū)域的一種形態(tài)學(xué)處理方法。
開運(yùn)算是先進(jìn)行腐蝕,再進(jìn)行膨脹的一種形態(tài)學(xué)處理方法。開運(yùn)算可以去除一些孤立的、細(xì)小的亮區(qū)域,平滑有毛刺的邊緣線,同時原區(qū)域的面積不會發(fā)生明顯變化。對于灰度值高于產(chǎn)品灰度值的(亮)劃痕可用頂帽算法檢測出來。
3.什么是黑帽算法?
黑帽算法是將閉運(yùn)算圖像(逐像素)減去原始的圖像,得到閉運(yùn)算中消除的小面積的局部暗像素區(qū)域的一種形態(tài)學(xué)處理方法。
閉運(yùn)算是先進(jìn)行膨脹,再進(jìn)行腐蝕的一種形態(tài)學(xué)處理方法。閉運(yùn)算可以去除一些孤立的、細(xì)小的暗區(qū)域,同時原區(qū)域的面積不會發(fā)生明顯變化。閉運(yùn)算還可以填充小面積的亮區(qū)域的空洞,使分離的亮邊緣相連接。對于灰度值低于產(chǎn)品灰度值的(暗)劃痕可用黑帽算法檢測出來。
二、劃痕檢測特點(diǎn)
1.依賴形態(tài)學(xué)處理
需要將檢測圖像轉(zhuǎn)換成二值化圖像,并使用形態(tài)學(xué)處理圖像突出檢測特征。
2.無固定形狀特征
劃痕都是隨機(jī)出現(xiàn)的無特定形狀的特征,因此無法通過匹配進(jìn)行檢測。
3.基于BLOB檢測
提取出劃痕特征后需要使用BLOB檢測出連通的劃痕區(qū)域。
4.需要一定對比度
劃痕和待檢測產(chǎn)品需要滿足一定的對比度,才能使用形態(tài)學(xué)處理方法提取對應(yīng)特征。
1.打開ZDevelop軟件:新建項(xiàng)目→新建HMI文件→新建main.bas文件,用于編寫界面響應(yīng)函數(shù)→新建global_variable.bas文件用于存放全局變量并開啟HMI自動運(yùn)行任務(wù)→新建InitParam.bas文件用于初始化測量參數(shù)→新建camera.bas文件用于實(shí)現(xiàn)相機(jī)采集功能→新建draw.bas文件用于更新繪制圖形刷新界面→文件添加到項(xiàng)目。
2.設(shè)計(jì)HMI界面。
3.在global_variable.bas文件中定義全局變量,定義完成后運(yùn)行Hmi.hmi文件。
'''''全局變量大部分使用數(shù)組結(jié)構(gòu)'''''
''注:basic編程中很多函數(shù)會以TABLE(系統(tǒng)的數(shù)據(jù)結(jié)構(gòu))做為參數(shù)
''在這里table均是做為中間變量
''table 21-22,鼠標(biāo)按鍵,控件坐標(biāo)系
''table 31-35,旋轉(zhuǎn)矩ROI參數(shù),cx、cy、width、height、angle,控件坐標(biāo)系
''table 41-45,旋轉(zhuǎn)矩形控件坐標(biāo)轉(zhuǎn)換后對應(yīng)的圖像坐標(biāo),圖像坐標(biāo)系
''table 51-56,圓環(huán)ROI參數(shù),cx、cy、圓環(huán)中線半徑r、圓環(huán)半寬ann_R、起始角度stAngle、角度范圍entAngle,控件坐標(biāo)系
''table 61-66,圓環(huán)控件坐標(biāo)轉(zhuǎn)換后對應(yīng)的圖像坐標(biāo),圖像坐標(biāo)系
'主任務(wù)狀態(tài)
'0 - 未初始化
'1 - 停止
'2 - 運(yùn)行中
'3 - 正在停止
GLOBAL DIM main_task_state
main_task_state = 1
'采集開關(guān)
'0 - 停止采集
'1 - 請求采集
GLOBAL DIM grab_switch
grab_switch = 0
'相機(jī)個數(shù)
GLOBAL cam_num
cam_num = 0
'相機(jī)種類,"zmotion;mvision;basler;mindvision;huaray"
GLOBAL DIM CAMERA_TYPE(16)
CAMERA_TYPE = "mvision"
' 定義主任務(wù)id - 10
GLOBAL DIM main_task_id
main_task_id = 10
'定義連續(xù)采集任務(wù)id - 9
GLOBAL DIM grab_task_id
grab_task_id = 9
'定義全局圖像變量
GLOBAL ZVOBJECT grabImg '采集圖像
GLOBAL ZVOBJECT binImg '二值化圖像
GLOBAL ZVOBJECT disImg '顯示圖像
'定義常用顏色變量
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_def_num '定義劃痕數(shù)量結(jié)果
GLOBAL DIM d_def_state '定義狀態(tài)結(jié)果
'定義劃痕數(shù)據(jù)結(jié)果存儲數(shù)組變量
GLOBAL DIM value(10000),id
'旋轉(zhuǎn)矩形ROI參數(shù):cx、cy、width、height、angle
GLOBAL DIM d_roi_rect2(5)
'檢測參數(shù):劃痕類型、檢測方向、檢測尺寸、對比度、最小面積、最大面積
GLOBAL DIM d_detect_param(6)
'***********定義讀取本地文件功能相關(guān)變量**************
''注意,該功能只在使用仿真器時有效
'定義是否使用本地圖片標(biāo)志
GLOBAL DIM d_use_imgfile
d_use_imgfile=1
'定義本地圖片索引
GLOBAL DIM d_index
d_index=0
'定義讀取圖片的路徑
GLOBAL DIM File_Name(100)
'***********結(jié)束定義讀取本地文件功能相關(guān)變量**********
'運(yùn)行HMI文件
RUN "Hmi.hmi",1
4.在InitParam.bas文件中初始化測量參數(shù)。
end
GLOBAL SUB init_detect_param()'初始化測量參數(shù)
d_def_num = 0 '劃痕結(jié)果初始化為0
d_def_state = 0 '狀態(tài)結(jié)果初始化為0
TABLE(1)=1
'初始化roi參數(shù)
d_roi_rect2(0) = 160.0 'roi中心x
d_roi_rect2(1) = 120.0 'roi中心y
d_roi_rect2(2) = 80.0 'roi寬
d_roi_rect2(3) = 60.0 'roi高
d_roi_rect2(4) = 0.0 'roi角度
TABLE(31) = d_roi_rect2(0) '將roi變量賦值給起始地址為31的table數(shù)組
TABLE(32) = d_roi_rect2(1)
TABLE(33) = d_roi_rect2(2)
TABLE(34) = d_roi_rect2(3)
TABLE(35) = d_roi_rect2(4)
'初始化檢測參數(shù):劃痕類型、檢測方向、檢測尺寸、對比度、最小面積、最大面積
d_detect_param(0) = 0 '初始化劃痕類型為暗
d_detect_param(1) = 2 '初始化檢測方向?yàn)閄軸和Y軸
d_detect_param(2) = 4 '初始化檢測尺寸為4
d_detect_param(3) = 20 '初始化對比度為20
d_detect_param(4) = 2000 '初始化最小面積為2000個像素
d_detect_param(5) = 7000 '初始化最大面積為7000個像素
'將劃痕結(jié)果變量賦值為0
for i=0 to 100
value(i)=0
next
END SUB
5.關(guān)聯(lián)HMI界面值顯示控件變量。
6.在main.bas文件中添加HMI界面初始化函數(shù)并在Hmi系統(tǒng)設(shè)置中關(guān)聯(lián)初始化函數(shù)。
'HMI界面初始化函數(shù)
GLOBAL SUB hmi_init()
grab_switch = 0 '初始化采集開關(guān)為停止采集
main_task_state = 1 '初始化主任務(wù)狀態(tài)為停止?fàn)顟B(tài)
'初始化時依據(jù)圖像分辨率設(shè)置區(qū)域的裁剪尺寸,此處圖像分辨率為1280x960
ZV_RESETCLIPSIZE(1280, 960)
'設(shè)置鎖存通道0的大小,以適應(yīng)圖片元件控件大小
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 7), HMI_CONTROLSIZEY(10, 7))
ZV_SETSYSINT("LineWidth",5) '設(shè)置繪制畫筆寬度為5個像素
init_detect_param() '初始化測量參數(shù)
ZV_LATCHCLEAR(0) '清空鎖存通道0
ZV_LATCHCLEAR(1) '清空鎖存通道1
END SUB
7.在camera.bas文件中添加HMI界面中采集相關(guān)按鈕響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)。
end
'主界面按下掃描相機(jī)按鈕時響應(yīng)的函數(shù)
GLOBAL SUB cam_scan_all()
if(d_use_imgfile=1)then
?"請先按下使用本地圖片按鈕關(guān)閉該功能"
return
endif
ZV_SETSYSINT("LogLevel", 7) '設(shè)置控制器信息
ZV_SETSYSSTR("DataDir","")
CAM_SCAN(CAMERA_TYPE) '掃描相機(jī),CAMERA_TYPE="mvision"
cam_num = CAM_COUNT() '獲取掃描到的相機(jī)數(shù)量
if (0 = cam_num) then '如果相機(jī)數(shù)量=0,打印提示信息
? "未找到相機(jī)"
return '退出子函數(shù),不往下執(zhí)行
endif
?"cam_num = " cam_num '如果掃描到相機(jī),打印相機(jī)數(shù)量
CAM_SEL(0) '選擇掃描到的第一個相機(jī)進(jìn)行操作
CAM_SETEXPOSURE(5000) '設(shè)置相機(jī)曝光時間為5000us
CAM_SETMODE(0) '設(shè)置軟件觸發(fā)模式
CAM_START(0) '開啟相機(jī)
END SUB
'主界面按下單次采集按鈕執(zhí)行的函數(shù)
GLOBAL SUB btn_grab()
'如果d_use_imgfile=1時使用讀取本地圖片功能,使用控制器時請將此部分代碼注釋掉
if (d_use_imgfile=1) then
if(d_index=3) then
d_index=0
endif
File_Name="\9"+TOSTR(d_index,1,0)+".bmp" '.../flash/9/目錄下的圖片所在的路徑名稱
ZV_IMGREAD(grabImg,File_Name,1)
ZV_LATCH(grabImg, 0)
d_index=d_index+1
return
endif
''讀取本地圖片功能結(jié)束
'如果相機(jī)數(shù)量為0,提示先掃描相機(jī),并退出子函數(shù)不往下執(zhí)行
if cam_num = 0 then
?"請先掃描相機(jī)!"
return
endif
CAM_SETPARAM("TriggerSoftware", 0) '發(fā)送觸發(fā)指令
CAM_GET(grabImg, 0) '獲取一幀圖像存放到grabImg變量中
ZV_LATCH(grabImg, 0) '將圖像顯示到鎖存通道0中
END SUB
'主界面按下連續(xù)采集按鈕響應(yīng)的函數(shù)
GLOBAL SUB btn_cgrab()
if grab_switch =1 then '如果已經(jīng)處于連續(xù)執(zhí)行狀態(tài),打印提示信息并退出函數(shù)
?"正在連續(xù)運(yùn)行中,請勿重復(fù)操作!"
return
endif
if( d_use_imgfile =0) then '如果使用相機(jī)采集功能
if cam_num = 0 then '判斷如果相機(jī)數(shù)量=0,打印提示信息并退出函數(shù)
?"請先掃描相機(jī)!"
return
endif
endif
grab_switch = 1 '采集任務(wù)開關(guān)置1
if (1 = grab_switch) then
if (0 = PROC_STATUS(grab_task_id)) then
RUNTASK grab_task_id, grab_task '開啟連續(xù)采集任務(wù)
endif
endif
END SUB
'采集任務(wù)實(shí)現(xiàn)函數(shù)
grab_task:
while(1)
if (0 = grab_switch) then '如果采集任務(wù)開關(guān)=0即停止采集按鈕按下時
exit while '退出循環(huán)
endif
'grab_switch=1時重復(fù)執(zhí)行以下操作
btn_grab()'單次采集按鈕響應(yīng)的函數(shù)
wend
END
'主界面按下停止采集按鈕響應(yīng)的函數(shù)
GLOBAL SUB btn_stopCgrab()
if grab_switch =0 then '如果已經(jīng)處于停止采集狀態(tài),打印提示信息并退出函數(shù)
?"未開啟連續(xù)采集!"
return
endif
grab_switch = 0 '將采集任務(wù)開關(guān)置0
END SUB
8.在draw.bas文件中添加檢測ROI更新繪制函數(shù),并在自定義元件屬性窗口中關(guān)聯(lián)刷新函數(shù)和繪制函數(shù)。
end
'和繪制(即選擇ROI)有關(guān)的界面的刷新繪制函數(shù)放在這個bas文件里
DIM is_redraw '繪圖標(biāo)志,0表示未進(jìn)行繪制,1表示正在進(jìn)行繪制
is_redraw = 0
DIM hit_pos '定義調(diào)整操作標(biāo)志
'根據(jù)鼠標(biāo)操作更新ROI位置區(qū)域函數(shù)
GLOBAL SUB update_roi()
if mouse_scan(21) = 1 then '掃描鼠標(biāo)按下操作
'只有按下時可以改變擊中位置,獲取鼠標(biāo)點(diǎn)擊位置對應(yīng)的擊中區(qū)域編號
hit_pos = ZV_HMIADJRECT2(table(21), table(22), 31, -1)
is_redraw = 1 '繪圖標(biāo)志置1
endif
if mouse_scan(21) = -1 then '掃描鼠標(biāo)松開操作
'根據(jù)區(qū)域編號調(diào)整roi區(qū)域位置
ZV_HMIADJRECT2(table(21), table(22), 31, hit_pos)
is_redraw = 1 '繪圖標(biāo)志置1
endif
if (MOUSE_state(21)) then '鼠標(biāo)按下時
'根據(jù)區(qū)域編號調(diào)整roi區(qū)域位置
ZV_HMIADJRECT2(table(21), table(22), 31, hit_pos)
is_redraw = 1 '繪圖標(biāo)志置1
endif
if (1 = is_redraw) then '如果繪制標(biāo)志=1
is_redraw = 0 '繪圖標(biāo)志置0
'控件roi坐標(biāo)轉(zhuǎn)圖像roi坐標(biāo),控件坐標(biāo)存放在起始地址為111的數(shù)組,圖像坐標(biāo)存放在起始地址為50的數(shù)組
ZV_POSTOIMG(0, 1, 31, 41)
d_roi_rect2(0) = TABLE(41)'將圖像坐標(biāo)的數(shù)據(jù)賦值給ROI變量
d_roi_rect2(1) = TABLE(42)
d_roi_rect2(2) = ZV_LENTOIMG(0, TABLE(33))
d_roi_rect2(3) = ZV_LENTOIMG(0, TABLE(34))
d_roi_rect2(4) = TABLE(35)
SET_REDRAW '重新繪制全部區(qū)域
endif
END SUB
'ROI區(qū)域更新后實(shí)時繪制ROI區(qū)域
GLOBAL SUB draw_roi()
SET_COLOR(C_BLUE) '設(shè)置畫筆顏色為藍(lán)色
ZV_HMIRECT2(31, 300) '將旋轉(zhuǎn)矩形roi分解為HMI支持的繪圖圖元并添加控制參數(shù),便于HMI繪圖顯示
DRAWLINE(TABLE(300), TABLE(301), TABLE(302), TABLE(303)) '繪制外矩形
DRAWLINE(TABLE(302), TABLE(303), TABLE(304), TABLE(305))
DRAWLINE(TABLE(304), TABLE(305), TABLE(306), TABLE(307))
DRAWLINE(TABLE(306), TABLE(307), TABLE(300), TABLE(301))
END SUB
9.在main.bas文件中添加HMI界面按下【上一頁】按鈕時響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)名。
'HMI界面按下上一頁按鈕時響應(yīng)的函數(shù)
GLOBAL SUB last_()
id=id-1 'id變量自減1
if id<0 then '如果id變量<0
id =0 'id=0
endif
END SUB
10.在main.bas文件中添加HMI界面按下【下一頁】按鈕時響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)名。
'HMI界面按下下一頁按鈕時響應(yīng)的函數(shù)
GLOBAL SUB next_()
id=id+1 'id變量自加1
END SUB
11.在main.bas文件中添加HMI界面按下【測試】按鈕時響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)名。
'HMI界面按下測試按鈕時響應(yīng)的函數(shù)
GLOBAL SUB btn_test()
for i=0 to 100 '檢測前先將結(jié)果數(shù)據(jù)清零
value(i)=0
next
'定義二值化白色區(qū)域、二值化區(qū)域、二值化黑色區(qū)域、連通區(qū)域、檢測結(jié)果、劃痕輸出圖像、輸出結(jié)果矩陣、結(jié)果列表
GLOBAL ZVOBJECT regionWhite, regionMask, regionBlack,re_connecte,rst,outImg,mat,relist
'根據(jù)ROI數(shù)據(jù)生成檢測區(qū)域ROI
ZV_REGENRECT2(regionMask, d_roi_rect2(0), d_roi_rect2(1), d_roi_rect2(2), d_roi_rect2(3), d_roi_rect2(4))
'表面外觀缺陷檢測算子,傳參分別是:輸入圖像、檢測區(qū)域、輸出檢測結(jié)果、檢測劃痕類型、檢測軸、檢測尺寸、對比度閾值、最小面積、最大面積
ZV_DEFDETECTSUR_(grabImg,regionMask,rst,d_detect_param(0),d_detect_param(1),d_detect_param(2),d_detect_param(3),d_detect_param(4),d_detect_param(5))
'獲取缺陷結(jié)果算子,傳參分別是:檢測結(jié)果、輸出缺陷圖像、數(shù)據(jù)結(jié)果矩陣、結(jié)果列表、輸出圖像類型、輸出結(jié)果排序類型
ZV_DEFGETSURRST_(rst,outImg,mat,relist,2,0)'獲取缺陷結(jié)果
ZV_LATCH(outImg,1)'將缺陷結(jié)果圖像顯示到鎖存通道1中
ZV_MATINFO(mat,50)'獲取結(jié)果矩陣的信息并存放到起始地址為50的變量中
d_def_num=table(50)'將矩陣行數(shù)即劃痕數(shù)量賦值給結(jié)果變量
if (TABLE(50)=0) then '如果檢測到的劃痕數(shù)量=0,則結(jié)果狀態(tài)=1
d_def_state=1
else d_def_state=0
endif
?TABLE(50),TABLE(51)'打印提示矩陣的行數(shù)和列數(shù)信息
for i = 0 to TABLE(50)-1 '循環(huán)給數(shù)據(jù)結(jié)果變量賦值
'獲取第i行矩陣數(shù)據(jù)結(jié)果,包括面積 周長,坐標(biāo)x,坐標(biāo)y
ZV_MATGETROW(mat, i, 4, 100+i*4)
value(i*4+0)=TABLE(100+i*4+0)'將table數(shù)據(jù)賦值給對應(yīng)變量
value(i*4+1)=TABLE(100+i*4+1)
value(i*4+2)=TABLE(100+i*4+2)
value(i*4+3)=TABLE(100+i*4+3)
next
END SUB
12.在main.bas文件中添加【運(yùn)行】按鈕響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)。
HMI界面按下運(yùn)行按鈕時響應(yīng)的函數(shù)
GLOBAL SUB btn_run()
if(2 = main_task_state) then '如果主任務(wù)處于運(yùn)行中狀態(tài)
?"已經(jīng)開啟連續(xù)運(yùn)行任務(wù),請勿重復(fù)操作!" '打印提示
return
endif
if (1 = main_task_state) then '如果主任務(wù)處于停止?fàn)顟B(tài)
if (0 = PROC_STATUS(main_task_id)) then'如果程序中任務(wù)未開啟
main_task_state = 2 '將主任務(wù)狀態(tài)設(shè)置為運(yùn)行中狀態(tài)
RUNTASK main_task_id, main_task'開啟主任務(wù)
endif
endif
END SUB
'主任務(wù)執(zhí)行的函數(shù)
main_task:
while(1)
'如果主任務(wù)狀態(tài)處于正在停止?fàn)顟B(tài)即停止按鈕按下時
if (3 = main_task_state) then
main_task_state = 1'將主任務(wù)狀態(tài)設(shè)置為停止?fàn)顟B(tài)
exit while '退出循環(huán)
endif
'否則循環(huán)執(zhí)行采集和檢測函數(shù)
btn_grab()
btn_test()
wend
END
13.在main.bas文件中添加【停止】按鈕響應(yīng)的函數(shù)并關(guān)聯(lián)動作函數(shù)。
HMI界面按下停止按鈕時響應(yīng)的函數(shù)
GLOBAL SUB btn_stop()
if (2 = main_task_state) then '如果主任務(wù)狀態(tài)處于2即任務(wù)運(yùn)行中時
main_task_state = 3 '將主任務(wù)狀態(tài)置為3,退出循環(huán)
endif
END SUB
本次,正運(yùn)動技術(shù)VPLC系列機(jī)器視覺運(yùn)動控制一體機(jī)快速入門(九)——外觀檢測功能---檢測劃痕,就分享到這里。
-
機(jī)器視覺
+關(guān)注
關(guān)注
161文章
4325瀏覽量
120011 -
缺陷檢測
+關(guān)注
關(guān)注
2文章
142瀏覽量
12191 -
正運(yùn)動技術(shù)
+關(guān)注
關(guān)注
0文章
97瀏覽量
294
發(fā)布評論請先 登錄
相關(guān)推薦
評論