Blob分析:聚合具有某种相同属性(灰度值、文理、周长等等)的像素,或者进一步可以说尽量区分感兴趣区域与非感兴趣区域(或者前景与后景)。通过这种分析可以得到感兴趣区域(前景)的位置、形状、方向和拓扑关系等特征信息,为下一步操作铺垫,可以说是比较重要的一部操作。
需要注意的是,Blob分析对光照敏感!!!
Blob分析的主要技术:
- 图像分割
- 形态学操作
- 连通性分析
- 特征值计算
- 场景描述
这些技术可以穿插使用,并没有固定先后顺序,只要最后的结果满足项目需求即可。
1.下面通过Halcon的例程(电路板中定位焊接点)走一遍过程:方法->Blob分析->ball.hdev(Inspection of Ball Bonding)
* ball.hdev: Inspection of Ball Bonding
*设置图形窗口每一步是否更新显示,单步调试时影响不大。关注程序运行时间时应该关闭掉。
dev_update_window ('off')
dev_close_window ()
dev_open_window (0, 0, 728, 512, 'black', WindowID)
read_image (Bond, 'die/die_03')
dev_display (Bond)
*设置提示的字体
set_display_font (WindowID, 14, 'mono', 'true', 'false')
*设置提示信息的样式
disp_continue_message (WindowID, 'black', 'true')
stop ()
*二值化
threshold (Bond, Bright, 100, 255)
*变换区域的形状,这里输出的是最小外接矩形
shape_trans (Bright, Die, 'rectangle2')
*对图像操作后,设置用什么颜色显示结果
dev_set_color ('green')
*设置区域轮廓的线宽
dev_set_line_width (3)
*设置区域填充模式,有区域全部填充和只描区域边缘两种模式
dev_set_draw ('margin')
dev_display (Die)
disp_continue_message (WindowID, 'black', 'true')
stop ()
*从图像Bond中截取和区域Die一样大小的图像DieGrey。但是实际大小并没有变化
reduce_domain (Bond, Die, DieGrey)
threshold (DieGrey, Wires, 0, 50)
*填充具有某些特征(这里是面积特征)的孔洞,即:填充感性区域中有某些孔洞。区域的个数不变,面积增加
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 (WiresFilled, Balls, 15.5)
dev_set_color ('green')
dev_display (Balls)
disp_continue_message (WindowID, 'black', 'true')
stop ()
*将不具有连接的区域拆分成不同的区域
connection (Balls, SingleBalls)
*特征选择,这里是用圆似度进行选择
select_shape (SingleBalls, IntermediateBalls, 'circularity', 'and', 0.85, 1.0)
* 对图像中的区域进行排序(我觉得用编号这个词更好理解)。除了一种排序模式(character)外,其他模式
*都是按照区域中的某个点进行排序。比如这里是按照区域的第一行最前面的点进行列排序。
*之所以说用编号更好理解,排序在直观上是某些数值具有大小先后关系,用这个算子后各个区域并没有数值大小先后关系,
*仅仅是方便输出或者说遍历。
sort_region (IntermediateBalls, FinalBalls, 'first_point', 'true', 'column')
dev_display (Bond)
*对不同的区域设置用几种颜色显示,注意和dev_set_color()区分
dev_set_colored (12)
dev_display (FinalBalls)
disp_continue_message (WindowID, 'black', 'true')
stop ()
*获得区域的最小外接圆,并将这个圆的中心坐标和半径给(Row,Column)以及Radius。注意,传入的区域是经过
*排序(编号)了的,是数组格式,同样(Row,Column)以及Radius也是数组格式。
smallest_circle (FinalBalls, Row, Column, Radius)
NumBalls := |Radius|
Diameter := 2*Radius
meanDiameter := sum(Diameter)/NumBalls
mimDiameter := min(Diameter)
dev_display (Bond)
*在WindowID窗口中显示圆(必须有圆的中心坐标及半径)
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')
else
disp_message (WindowID, 'D: '+Diameter[i-1], 'image', Row[i-1]+1.2*Radius[i-1], max([Column[i-1]-60,0]), 'white', 'false')
endif
endfor
dev_set_color ('green')
dev_update_window ('on')
disp_continue_message (WindowID, 'black', 'true')
stop ()
dev_close_window ()
这里主要用到的是二值化、开运算、连通性分析以及特征选择等方法提取感性区域。
2.自己动手实现一个Blob分析:五毛钱币定位
Halcon代码如下:
* Code generated by Image Acquisition 01
dev_update_window ('off')
dev_close_window ()
dev_open_window (0, 0, 728, 512, 'black', WindowID)
*读图并灰度化
read_image (Image, 'E:/HalconCodeing/image/five_r_1.jpg')
dev_display (Image)
rgb1_to_gray (Image, GrayImage)
dev_display (GrayImage)
*二值化后进行开运算
dev_set_color ('red')
threshold (GrayImage, Regions, 123, 241)
dev_display (Regions)
dev_set_color ('green')
opening_circle (Regions, RegionOpening, 11)
dev_display (RegionOpening)
*非连同区域拆分
dev_set_colored (12)
connection (RegionOpening, ConnectedRegions)
dev_display (ConnectedRegions)
*选择目标区域
dev_set_color ('red')
select_shape (ConnectedRegions, SelectedRegions, ['area','circularity'], 'and', [13590,0.93959], [31864.1,0.97679])
dev_display (SelectedRegions)
*获得外接圆并定位
smallest_circle (SelectedRegions, Row, Column, Radius)
dev_display (Image)
disp_circle (WindowID, Row, Column, Radius)
disp_message (WindowID, '坐标:'+'('+Row+','+Column+')'+' '+'R:'+Radius, 'image', Row-2*Radius-5, Column-3*Radius-10, 'black', 'true')
结果图如下:
用摄像头采集图片进行实验更好,毕竟可以完整的走一下流程。不过我没有这样的设备,只能用手机拍个照片简单的模拟实现一下。
模拟一下这个过程,也发现了Halcon编程的几个特点(或者说需要注意的点)和几个疑惑:
特点:
- 结果显示感觉有点复杂,可以通过代码控制和编辑菜单栏中可视化控制;而且还杂糅了图形窗口总是或者从不等更新选项;
- 最后显示结果不对时,有可能是这一步结果和上一步结果重叠在一起导致显示结果和预想不同。所以对于我这种初学者推荐每一步操作后都设置一下显示算子。比如dev_set_color和dev_display结合使用等。
- 由于Halcon显示窗口只有一个,和其他的IDE可能又有所不同,所以在用Halcon转成其他代码时需要注意图形窗口显示是否满足其他IDE要求。
疑惑:
- 图片中的最小元素不是像素吗,为什么半径的结果还有四位的小数,其实在调试过程中也发现了面积等也有小数。不知道这是为啥?
- 如果我记得没错的话,在OpenCV中腐蚀与膨胀的那个核只能奇数(比如3,5,11等),至少也是整数,但是在Halcon中不光可以用偶数也可以用小数,不知道Halcon底层是怎么实现这些的?
3.Blob分析其他内容:预处理
在进行Blob分析之前有可能需要图片的预处理。预处理内容包括:中值滤波、均值滤波、高斯滤波(根据离核中心距离进行加权滤波)和模板(第一种:核中最大和最小像素相减,用于拉大对比度;第二种:灰度腐蚀与膨胀;第三种:灰度的线性变换)。下面列出这些预处理的具体实例。
- 中值滤波 二维码识别->2d_data_codes_minimize_noise.hdev
- 均值滤波
- 高斯滤波
- 模板 光学字符识别->engraved.hdev(Read characters on a metal surface)