measure_ball_bond.hdev
dev_update_off ()
dev_close_window ()
FileName := 'bonds/ball_bond_ccd_'
read_image (Image, FileName + 1$'02')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_set_line_width (2)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_draw ('margin')
get_system ('store_empty_region', StoreEmptyRegion)
set_system ('store_empty_region', 'false')
*
NumImages := 6
for Index := 1 to NumImages by 1
read_image (Image, FileName + Index$'02')
dev_display (Image)
*
* Extract pads on chip
*计时器开始
count_seconds (S1)
*利用阈值把白色底座提取出来
threshold (Image, Region, 135, 255)
*连通各区域
connection (Region, ConnectedRegions)
*利用长宽和面积特征去除无用区域
select_shape (ConnectedRegions, SelectedRegions, ['width','height','area'], 'and', [115,115,5000], [130,130,15000])
*填补区域内的漏洞
fill_up (SelectedRegions, RegionFillUp)
*变换区域形状,利用‘convex’凸包性,得到把目标区域包围起来的矩形
shape_trans (RegionFillUp, Pads, 'convex')
*
* Segment ball bonds on pad
*差分
difference (Pads, RegionFillUp, RegionDifference)
*开操作
opening_rectangle1 (RegionDifference, BondWire, 10, 10)
*变换区域形状,利用内接圆
shape_trans (BondWire, BallBonds, 'inner_circle')
select_shape_proto (Pads, BallBonds, MissingBonds, 'overlaps_rel', 0, 0)
count_seconds (S2)
Time := (S2 - S1) * 1000
*
* Get the contours of the pads with subpixel precision
*在原半径上增加10,向外扩展圆
dilation_circle (BallBonds, RegionDilation2, 10)
*只保留区域2在区域1中的区域(前者区域1,中间区域2,后者为结果)
intersection (RegionDilation2, BondWire, RegionIntersection)
*向内扩散一个像素的区域
boundary (RegionIntersection, RegionBorder, 'inner')
*内外各以3.5的像素扩大区域
dilation_circle (RegionBorder, RegionDilation, 3.5)
*将区域合并返回
union1 (RegionDilation, RegionUnion)
*提取出区域(不是裁剪)
reduce_domain (Image, RegionUnion, ImageReduced)
*使用累计直方图计算两个阀值。凡是大于高阀值的一定是边缘; 凡是小于低阀值的一定不是边缘;
*如果检测结果大于低阀值但又小于高阀值,那就要看这个像素的邻接像素中有没有超过高阀值的边缘像素:如果有的话那么它就是边缘了,否则他就不是边缘;
*但我仍然有疑惑
edges_sub_pix (ImageReduced, Edges, 'canny', 1, 20, 70)
*合并轮廓,之前的轮廓由好几条线组成
union_adjacent_contours_xld (Edges, UnionContours, 10, 1, 'attr_keep')
*根据特征选择轮廓,上一步中还有多余的轮廓线
select_contours_xld (UnionContours, SelectedContours, 'contour_length', 20, 20000, -0.5, 0.5)
*根据轮廓线拟合一个圆,得到圆心坐标,半径
fit_circle_contour_xld (SelectedContours, 'atukey', -1, 0, 0, 5, 7, CircleRow, CircleColumn, Radius, StartPhi, EndPhi, PointOrder)
*根据圆心坐标和半径产生一个圆
gen_circle_contour_xld (ContCircle, CircleRow, CircleColumn, Radius, 0, 6.28318, 'positive', 1)
*
* Display the results obtained so far
*计数
count_obj (BondWire, NBonds)
*创建一个空元组
gen_empty_obj (MeasureArrows)
*
*
dev_display (Image)
dev_set_color ('cyan')
dev_display (ContCircle)
dev_set_color ('magenta')
*
* Evaluate and display the results
area_center (RegionDilation2, Area, Row, Column)
area_center (MissingBonds, AreaM, RowM, ColumnM)
select_shape_proto (Pads, BallBonds, BallTooClose, 'distance_contour', 0, 10)
area_center (BallTooClose, AreaB, RowB, ColumnB)
dev_set_color ('yellow')
dev_display (Pads)
if (|AreaM| > 0 or |AreaB| > 0)
dev_set_color ('red')
dev_display (MissingBonds)
dev_display (BallTooClose)
for IndexE := 0 to |AreaM| - 1 by 1
NRow := RowM[IndexE]
NCol := ColumnM[IndexE]
disp_message (WindowHandle, 'Ball bond\nis missing', 'image', NRow - 150, NCol - 110, 'red', 'true')
endfor
for IndexE := 0 to |AreaB| - 1 by 1
NRow := RowB[IndexE]
NCol := ColumnB[IndexE]
disp_message (WindowHandle, 'Ball bond is too\nclose to border', 'image', NRow - 150, NCol - 150, 'red', 'true')
endfor
endif
for IndexM := 1 to NBonds by 1
*选择其中一个对象
select_obj (ContCircle, ObjectSelected, IndexM)
*计算这个轮廓的外接矩形
smallest_rectangle1_xld (ObjectSelected, minY, minX, maxY, maxX)
* Draw arrow corresponding to the diameter of the fitted circle
*计算轮廓的面积和中心坐标
area_center_xld (ObjectSelected, Area1, Ybb, Xbb, PointOrder1)
*根据中心坐标和外接矩形上边的中心点产生一个箭头
gen_arrow_contour_xld (Arrow, Ybb, Xbb, minY, Xbb, 12, 12)
*将箭头放进创建的元组对象里
concat_obj (MeasureArrows, Arrow, MeasureArrows)
*根据中心坐标和外接矩形下边的中心点产生一个箭头
gen_arrow_contour_xld (Arrow, Ybb, Xbb, maxY, Xbb, 12, 12)
*将箭头放进创建的元组对象里
concat_obj (MeasureArrows, Arrow, MeasureArrows)
dev_set_color ('green')
dev_display (MeasureArrows)
select_obj (ContCircle, ObjectSelected, IndexM)
area_center_xld (ObjectSelected, Area2, Ybb, Xbb, PointOrder2)
disp_message (WindowHandle, (2 * Radius[IndexM - 1])$'.2f' + ' px', 'image', Ybb - 15, Xbb + 75, 'green', 'false')
endfor
disp_message (WindowHandle, |Row| + ' Ball Bond(s) detected\nin ' + Time$'.2f' + ' ms', 'window', 12, 12, 'black', 'true')
*
* Evaluate and display results
if (Index != NumImages)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
set_system ('store_empty_region', StoreEmptyRegion)