HALCON示例程序ball電路板焊點識別、檢測、測量程序剖析
示例程序源碼(加注釋)
介紹: ball.hdev: Inspection of Ball Bonding
*halcon窗口實時更新關閉
dev_update_window (‘off’)
*halcon關閉所有窗口
dev_close_window ()
*halcon打開新窗口
dev_open_window (0, 0, 728, 512, ‘black’, WindowID)
*讀入圖像
read_image (Bond, ‘die/die_03’)
*halcon顯示讀入圖像
dev_display (Bond)
*halcon設置在“WindowID”界面中字體顯示格式
*函數原型:set_display_font( : : WindowHandle, Size, Font, Bold, Slant : )
*函數原型:WindowHandle:設置的窗口ID;Size:字體大小;Font:字體(宋體、楷體。。。。。);Bold:是否加粗;Slant :是否使用斜體
set_display_font (WindowID, 14, ‘mono’, ‘true’, ‘false’)
*disp_continue_message 此函數會在屏幕右下角顯示“單擊”“運行”使程序繼續運行。(其實就是加一個繼續按鈕)
*disp_continue_message(:: WindowHandle,Color,Box ?
*WindowID:顯示的窗口;Color:顯示顏色;Box :是否顯示底色
disp_continue_message (WindowID, ‘black’, ‘true’)
*程序暫停運行,以便于查看
stop ()
*選中Bond圖片中像素值于100-255的像素,生成一個區域Bright
threshold (Bond, Bright, 100, 255)
*求取剛剛提取出的區域的最小外接矩形,名稱為Die
shape_trans (Bright, Die, ‘rectangle2’)
*設置顯示的顏色(包括字體、區域、ROI等)
dev_set_color (‘green’)
*設置顯示線寬
dev_set_line_width (3)
*設置顯示區域的方式margin:邊緣模式(顯示區域只劃出他的外邊緣);Fill:填充模式(以填充方式顯示區域)
dev_set_draw (‘margin’)
*顯示剛剛求得的最小外接矩形
dev_display (Die)
disp_continue_message (WindowID, ‘black’, ‘true’)
stop ()
*剪裁圖片,用區域Die去裁剪圖片Bond,生成新的圖片DieGrey
reduce_domain (Bond, Die, DieGrey)
*閾值選取
threshold (DieGrey, Wires, 0, 50)
*填充區域內的孔洞(不同于fillup)具有特征選擇的功能,這里用到的使面積,不在最小最大設定范圍的孔洞將不會被填充
*函數原型:fill_up_shape(Region:RegionFillUp:Feature,Min,Max:)
*Region:區域;RegionFillUp:填充后的區域;Min:最小填充孔洞;Max:最大填充孔洞
fill_up_shape (Wires, WiresFilled, ‘area’, 1, 100)
*顯示與相關設置(這些之前都介紹過哈)
dev_display (Bond)
dev_set_draw (‘fill’)
dev_set_color (‘red’)
dev_display (WiresFilled)
disp_continue_message (WindowID, ‘black’, ‘true’)
stop ()
*使用圓形元素進行開運算(開運算就是把區域變小,要留住圓形的區域就用圓形開運算,要留住矩形區域就用矩形元素去開運算)
*函數原型:opening_circle(Region : RegionOpening : Radius : )
*Region :要進行開運算的區域;RegionOpening :開運算過后的區域;Radius :用于開運算元素的半徑
*這里就是要去掉圓形焊點后邊的小尾巴
opening_circle (WiresFilled, Balls, 15.5)
*又是相關的顯示設置了
dev_set_color (‘green’)
dev_display (Balls)
disp_continue_message (WindowID, ‘black’, ‘true’)
stop ()
*分割連通域,我們做了上述的這么多事情,怎么才能把焊盤一個一個的找出來呢,雖然現在接近成功,但還不行,因為現在的區域還是一個,(就如CAD的圖層與PS的圖層差不多)就是雖然不相連但是還是認為是一坨,connection就是把這些不相連的給分成不同的區域。兩個參數,第一個是傳入區域(要分割的);第二個是分割后的。在halcon上最直觀的顯示就是由一個顏色變得五彩繽紛了
connection (Balls, SingleBalls)
*特征選擇函數,選擇特定的特征是我們做簡單的圖像分析常用的算子。可以通過區域的特征(面積、圓度、矩形度。。。。。)不同篩選出我們要的區域。
*這里用到的使圓度;圓度介于0.85-1.0的區域將會被選中
select_shape (SingleBalls, IntermediateBalls, ‘circularity’, ‘and’, 0.85, 1.0)
*sort_region - 根據區域的相對位置對區域進行排序
*函數原型:sort_region(Regions:SortedRegions:SortMode,Order,RowOrCol ?
*Regions:區域們;SortedRegions:對區域排序完成的區域;SortMode:排序模式;Order:順序還是倒序;RowOrCol :行優先還是列優先
sort_region (IntermediateBalls, FinalBalls, ‘first_point’, ‘true’, ‘column’)
*又是相關的顯示設置了
dev_display (Bond)
dev_set_colored (12)
dev_display (FinalBalls)
disp_continue_message (WindowID, ‘black’, ‘true’)
stop ()
*求最小外接圓。到此焊點就都提取出來了,尺寸也出來了,焊點位置也出來了
smallest_circle (FinalBalls, Row, Column, Radius)
*下邊的就是計算與顯示相關的一些操作了
NumBalls := |Radius|
Diameter := 2 * Radius
meanDiameter := sum(Diameter) / NumBalls
mimDiameter := min(Diameter)
dev_display (Bond)
disp_circle (WindowID, Row, Column, Radius)
dev_set_color (‘white’)
for i := 1 to NumBalls by 1
*這里大家仔細看一下就明白了
if (fmod(i,2) == 1)disp_message (WindowID, 'D: ' + Diameter[i - 1], 'image', Row[i - 1] - 2.7 * Radius[i - 1], max([Column[i - 1] - 60,0]), 'white','false')elsedisp_message (WindowID, 'D: ' + Diameter[i - 1], 'image', Row[i - 1] + 1.2 * Radius[i - 1], max([Column[i - 1] - 60,0]),'white','false')endifendfor
dump_window (WindowID, ‘tiff_rgb’, ‘./ball’)
dev_set_color (‘green’)
dev_update_window (‘on’)
disp_continue_message (WindowID, ‘black’, ‘true’)
stop ()
dev_close_window ()
處理思路
這個焊點檢測拿到圖片后我們想到的他的一個特點是圓的對吧,在一個我們看一下像素值很低,這個例程就是使用了這個特性完成了這個。先對電路板進行了一個選取,減少非電路板部分對檢測的干擾。然后通過閾值選擇出焊點,因為照片噪點或者產品本身就有噪點,對封閉區域做了一個填充。但是影響因素很多,這時使用圓形元素進行了一個開運算,搞掉那些影響。之后進行了特征篩選,用到了圓度這一特性進行篩選。輕易的就選出了圓形焊點區域,之后做了一個簡單地排序與計算最后顯示出結果,大功告成。
后記
大家有什么問題可以向我提問哈,我看到了第一時間回復,希望在學習的路上多多結交良師益友。