*该程序显示了如何在水平对准的晶圆上找到管芯
*
* 显示初始化
read_image (WaferDies, 'wafer_dies')
dev_close_window ()
dev_open_window_fit_image (WaferDies, 0, 0, 700, 500, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
get_window_extents (WindowHandle, WindowRow, WindowColumn, WindowWidth, WindowHeight)
dev_update_off ()
dev_set_draw ('margin')
get_image_size (WaferDies, Width, Height)
dev_display (WaferDies)
dev_disp_text ('Image of a wafer', 'window', 12, 12, 'black', [], [])
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
* 1. 通过使用自动关联确定芯片的尺寸
*
rft_generic (WaferDies, ImageFFT, 'to_freq', 'none', 'complex', Width) //计算图像的实值快速傅立叶变换。时域到频域
correlation_fft (ImageFFT, ImageFFT, CorrelationFFT) //在频域中计算两个图像的相关性。
rft_generic (CorrelationFFT, Correlation, 'from_freq', 'n', 'real', Width) //频域到时域
*排除图像边界处的局部最大值。 提取图像左上角的最大值就足够了,因为自相关是一个偶函数。
gen_rectangle1 (Rectangle, 1, 1, Height / 2, Width / 2) //图像区域限定在左上1/4
reduce_domain (Correlation, Rectangle, CorrelationReduced)
*
*提取自动相关函数的局部最大值
local_max_sub_pix (CorrelationReduced, 'gauss', 2, 5000000, Row, Col)
*
*获得芯片的尺寸
* 找到最接近原点的最大值,此最大值对应于芯片的相对矩形角。
distance_pp (gen_tuple_const(|Row|,0), gen_tuple_const(|Col|,0), Row, Col, Distance) //(gen_tuple_const(|Row|,0) 创建一个具有|Row|个元素的,每个元素都为0的数组,计算到原点的距离
SortedIndex := sort_index(Distance) //排序,注意SortedIndex=[0, 2, 4, 1, 3],是先排序,再得到索引
Distance正确的排序:180,231,255,300,333,对应原原来数组中的位置刚好是[0,2,4,1,3]
Row1 := Row[SortedIndex[0]] //选择距离原点最近的局部最大值
Col1 := Col[SortedIndex[0]]
DiagonalLength := sqrt(Row1 * Row1 + Col1 * Col1)
Phi := atan2(Row1,Col1)
DieWidth := DiagonalLength * cos(Phi)
DieHeight := DiagonalLength * sin(Phi)
*
* 中心,第一个最大值和第二个最大值 一起定义芯片的方向和尺寸。
dev_set_color ('blue')
gen_cross_contour_xld (Crosses, Row, Col, 10, 0.785398)
gen_ellipse_contour_xld (Circle, Row1, Col1, 0, 12, 12, 0, 6.28318, 'positive', 1.5)
dev_display (Correlation)
dev_display (Crosses)
dev_display (Circle)
dev_set_color ('green')
dev_display (Rectangle)
dev_disp_text ('Autocorrelation, region of interest, and local maxima', 'window', 12, 12, 'black', [], [])
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
* 可视化提取图片大小
gen_rectangle2_contour_xld (Die, Height / 2, Width / 2, 0, DieWidth / 2, DieHeight / 2)
dev_display (WaferDies)
dev_set_color ('blue')
dev_display (Die)
dev_disp_text ('Extracted die size', 'window', 12, 12, 'black', [], [])
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
* 2.通过使用基于形状的匹配来确定芯片的位置
*
LineWidth := 7 //每个芯片间隙的宽度
LineWidthFraction := 0.6
*
*生成芯片之间线条的人工模型图像
gen_image_const (Template, 'byte', Width, Height) //创建具有恒定灰度值的图像
scale_image (Template, Template, 1, 128) //缩放图像的灰度值
RefRow := round(0.5 * Height) //rand最邻近整数,即四舍五入
RefCol := round(0.5 * Width)
for Row := -0.5 to 0.5 by 1
for Col := -0.5 to 0.5 by 1
gen_rectangle2_contour_xld (Rectangle, RefRow + Row * DieHeight, RefCol + Col * DieWidth, 0, 0.5 * DieWidth - 0.5 * LineWidth, 0.5 * DieHeight - 0.5 * LineWidth)
gen_rectangle2_contour_xld
官方解释:gen_rectangle2_contour_xld creates one or more XLD contours in the shape of a rectangle with arbitrary orientation. The rectangle has the center (Row, Column), the orientation Phi, and the half edge lengths Length1 and Length2.
gen_rectangle2_contour_xld 以任意方向创建一个或多个矩形的XLD轮廓。 矩形具有中心 center (Row, Column),方向Phi和半边长Length1和Length2。
这里做个解释:是图像中心点(RefRow RefCol)以 (-0.5,-0.5), (-0.5,0.5), (0.5,-0.5), (0.5,0.5)倍平移(DieHeight,DieWidth),刚好是4个相邻芯片的矩形坐在位置。
paint_xld (Rectangle, Template, Template, 0) //画出模板
endfor
endfor
gen_rectangle2_contour_xld (Rectangle, RefRow, RefCol, 0, 0.5 * LineWidthFraction * LineWidth, DieHeight)
(生成芯片 竖直 间隙)(每个矩形覆盖60%的线宽,LineWidthFraction := 0.6)
paint_xld (Rectangle, Template, Template, 0)
gen_rectangle2_contour_xld (Rectangle, RefRow, RefCol, 0, DieWidth, 0.5 * LineWidthFraction * LineWidth) //生成芯片 水平间隙
paint_xld (Rectangle, Template, Template, 0)
gen_rectangle2 (ROI, RefRow, RefCol, 0, DieWidth + 5, DieHeight + 5) //生成包含四个临近dies的矩形
reduce_domain (Template, ROI, TemplateReduced)
create_shape_model (TemplateReduced, 'auto', 0, 0, 'auto', 'auto', 'ignore_local_polarity', 'auto', 5, ModelID) //生成模板 ModelID
create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)
create_shape_model(
Template : : //reduce_domain后的模板图像
NumLevels, //金字塔的层数,可设为“auto”或0—10的整数
AngleStart,//模板旋转的起始角度
AngleExtent,//模板旋转角度范围, >=0
AngleStep,//旋转角度的步长, >=0 and <=pi/16
Optimization,//设置模板优化和模板创建方法
Metric, //匹配方法设置
Contrast,//设置对比度
MinContrast ://设置最小对比度
ModelID) //输出模板句柄
dev_display (Template)
dev_set_color ('blue')
dev_display (ROI)
dev_disp_text ('Template of 4 adjacent dies', 'window', 12, 12, 'black', [], []) //4个相邻dies的模板显示
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
*在原始图像中找到人工模型的最佳实例
MinScore := 0.7
Greediness := 0.5
NumMatches := 1
find_shape_model (WaferDies, ModelID, 0, 0, MinScore, NumMatches, 0.5, 'least_squares', 0, Greediness, MatchRow, MatchColumn, MatchAngle, MatchScore)
find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)
find_shape_model(Image : : //搜索图像
ModelID, //模板句柄
AngleStart, // 搜索时的起始角度
AngleExtent, //搜索时的角度范围,必须与创建模板时的有交集
MinScore, //最小匹配值,输出的匹配的得分Score 大于该值
NumMatches, //定义要输出的匹配的最大个数
MaxOverlap, //当找到的目标存在重叠时,且重叠大于该值时选择一个好的输出
SubPixel, //计算精度的设置,五种模式,多选2,3
NumLevels, //搜索时金字塔的层数
Greediness : //贪婪度,搜索启发式,一般都设为0.9,越高速度快,容易出现找不到的情况
Row, Column, Angle, Score) //输出匹配位置的行和列坐标、角度、得分。
*
get_shape_model_contours (ModelContours, ModelID, 1) //返回形状模型的轮廓表示
vector_angle_to_rigid (0, 0, 0, MatchRow, MatchColumn, MatchAngle, HomMat2D) //从点和角度计算刚性仿射变换
affine_trans_contour_xld (ModelContours, ContoursAffinTrans, HomMat2D) //对XLD轮廓应用任意仿射2D变换
dev_display (WaferDies)
dev_set_color ('blue')
dev_display (ContoursAffinTrans)
dev_disp_text ('Best match', 'window', 12, 12, 'black', [], [])
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
* 3.根据芯片的的尺寸和位置计算切割线
*
dev_clear_window ()
dev_display (WaferDies)
dev_set_color ('blue')
NumRowMax := ceil(Height / DieHeight)
NumColMax := ceil(Width / DieWidth)
for RowIndex := -NumRowMax to NumRowMax by 1
RowCurrent := MatchRow + RowIndex * DieHeight
gen_contour_polygon_xld (CuttingLine, [RowCurrent,RowCurrent], [0,Width - 1]) //从多边形(作为元组)生成XLD轮廓。
dev_display (CuttingLine)
endfor
for ColIndex := -NumColMax to NumColMax by 1
ColCurrent := MatchColumn + ColIndex * DieWidth
gen_contour_polygon_xld (CuttingLine, [0,Height - 1], [ColCurrent,ColCurrent])
dev_display (CuttingLine)
endfor
dev_disp_text ('Resulting cutting lines', 'window', 12, 12, 'black', [], [])
dev_disp_text (' End of program ', 'window', 'bottom', 'right', 'black', [], [])
总结:
1.自相关g是图像本身相关性(g*g),通过傅里叶变换将图像转换到频域并与其共轭相乘计算相关,最后频域得到的相关结果再反傅里叶变换回时域。
上图较亮的灰度值代表较高的相关值,cross代表图像左上1/4区域中的局部最大值,被圈住的是距离原点最近的局部最大值。
2.比较值得思考的地方:
(1)建立模板的时候,生成模板的矩形中心:以图像中心点(RefRow,RefCol)为中心,分别加上(-0.5,-0.5)、(-0.5,0.5)、(0.5,-0.5)、(0.5,0.5)倍的(DieHeight,DieWidth)
RefRow := round(0.5 * Height) //rand最邻近整数,即四舍五入
RefCol := round(0.5 * Width)
for Row := -0.5 to 0.5 by 1
for Col := -0.5 to 0.5 by 1
gen_rectangle2_contour_xld (Rectangle, RefRow + Row * DieHeight, RefCol + Col * DieWidth, 0, 0.5 * DieWidth - 0.5 * LineWidth, 0.5 * DieHeight - 0.5 * LineWidth)
(2)生成芯片dies的分割线时,采用最匹配模型 MatchRow加上:-6 to 6 by 1 倍芯片高DieHeight
for RowIndex := -NumRowMax to NumRowMax by 1
RowCurrent := MatchRow + RowIndex * DieHeight
gen_contour_polygon_xld (CuttingLine, [RowCurrent,RowCurrent], [0,Width - 1]) //从多边形(作为元组)生成XLD轮廓。
dev_display (CuttingLine)
endfor
为什么这么做我不太明白?