主要思想:
1.采集图像
2.用模板匹配定位
3.通过模板匹配,找到药品液位高度的参考线
4.以模板匹配找到的横坐标为待测区域横坐标,
以模板匹配找到的纵坐标上移135个像素为纵坐标。
以这两点为中心,形成宽度20,高度75的测量矩形。
在这个测量矩形区域里面找液面高度
5.|找到的液面高度和参考线的差值| > 15个像素就算不合格
6.显示NG和OK区域
*关闭窗口
dev_close_window ()
*更新
dev_update_off ()
*读取图片
read_image (Image, ‘ampoules/ampoules_01’)
*获取图像的大小
get_image_size (Image, Width, Height)
*打开一个宽高和图片大小一致的窗口
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
*设置线宽为2个像素
dev_set_line_width (2)
*设置填充方式
dev_set_draw (‘margin’)
*设置字体
set_display_font (WindowHandle, 16, ‘mono’, ‘true’, ‘false’)
*液位检测
*共有8张图片,依次检测
NumImages := 8
for Index := 1 to NumImages by 1
*加载图像
read_image (Image, ‘ampoules/ampoules_’ + Index$’.2d’)
*定义数组
ColumnEdges := []
*定义液位高度数组
FillLevelHeight := []
* 查找之前确定的药品帽子模板
find_shape_model (Image, ModelID, 0, 0, 0.7, 0, 0.1, ‘least_squares’, 0, 0.9, Row, Column, Angle, Score)
*求模板纵坐标的平均值
MeanRow := mean(Row)
*经过手动测量,发现这个模板的高度,往上移动160个像素是液位的参考高度
RefLevel := MeanRow - 160
*下面这句是个人写的,方便大家查看参考点的高度是多少
gen_cross_contour_xld (Cross1, RefLevel, Column[0], 10, Angle)
*显示待测图片
dev_display (Image)
*显示线宽
dev_set_line_width (1)
*显示颜色白色
dev_set_color (‘white’)
*根据液位的参考高度,画一个矩形区域
*当前的待测产品都整齐的摆放在一起测试,没有倾斜,没有高度不一致
gen_rectangle2 (AcceptLevel, RefLevel, mean(Column), 0, 30 + (max(Column) - min(Column)) / 2, Tolerance)
*显示这个矩形局域
dev_display (AcceptLevel)
*显示线宽为2个像素
dev_set_line_width (2)
* 检测每一个药品高度
Errors := 0
*|Score|就代表一次性找到多少个模板,代表里面有多少个小药瓶
for Idx := 0 to |Score| - 1 by 1
*行是参考的基准减去135,列是每次找到的模板的列
*其实就是去确定检测液体高度的区域。可以理解为横坐标为找到模板的匹配区域。纵坐标为检测区域
translate_measure (MeasureHandle, MeanRow - 135, Column[Idx])
*测一下页面的边,也就是一个灰度变化较大的地方。因为只检测一个’first’,所以得到页面的高度坐标
measure_pos (Image, MeasureHandle, 2, 7, ‘all’, ‘first’, RowEdge, ColumnEdge, Amplitude, Distance)
*把每个测量出的液位高度的坐标放在数组里面
FillLevelHeight := [FillLevelHeight,RowEdge]
*得到的行的坐标也放在数组容器里面
ColumnEdges := [ColumnEdges,ColumnEdge]
*画一个小叉,用于方便显示
gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 15, 0)
*以找到模板的横坐标为当前的横坐标,以找到液位高度为纵坐标。画一个宽度28,高度20像素的矩形框
gen_rectangle2 (FillLevel, RowEdge, ColumnEdge, 0, 28, 20)
*计算出的液位高度-根据瓶口高度确定的液位高度(参考线高度)与设定的15个像素做比较
if (abs(FillLevelHeight[Idx] - RefLevel) >= Tolerance)
*将液体的检测区域画出来,就是和前面的24行的gen_measure_rectangle2一致。这次为了显示更清晰,将高度写成了90个像素
gen_rectangle2 (ChamberSingle, MeanRow - 133, Column[Idx], 0, 35, 90)
*画一个叉,用于显示真实检测到的液位高度
gen_cross_contour_xld (Cross, FillLevelHeight[Idx], ColumnEdges[Idx], 15, 0)
*在测量到的液位高度上,以找到模板的横坐标为当前的横坐标,以找到液位高度为纵坐标。画一个宽度28,高度20像素的矩形框
gen_rectangle2 (FillLevel, FillLevelHeight[Idx], ColumnEdges[Idx], 0, 28, 20)
*错误数量+1
Errors := Errors + 1
*显示白色
dev_set_color (‘red’)
*显示液体区域
dev_display (ChamberSingle)
disp_message (WindowHandle, ‘NG’, ‘image’, FillLevelHeight[Idx] - 50, ColumnEdges[Idx] - 10, ‘red’, ‘false’)
else
*<15个像素,说明是OK的
disp_message (WindowHandle, ‘OK’, ‘image’, FillLevelHeight[Idx] - 50, ColumnEdges[Idx] - 10, ‘green’, ‘false’)
dev_set_color (‘green’)
endif
dev_display (FillLevel)
dev_display (Cross)
endfor
* 最终判断,如果错误数量>0,就显示NG
if (Errors > 0)
disp_message (WindowHandle, Errors + ’ BAD’, ‘window’, 10, 12, ‘red’, ‘true’)
else
disp_message (WindowHandle, ‘All OK’, ‘window’, 10, 12, ‘forest green’, ‘true’)
endif
if (Index < NumImages)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop ()
endif
endfor
对应示例程序:
measure_fill_level.hdev