图像处理(二)
halcon例程 inspect_solar_fingers.hdev 注释
Halcon中的几个窗口:
- 图形窗口
左上角坐标为(0,0),x轴向下延伸,y轴向右延伸,z轴代表灰度 - 变量窗口
- 程序窗口
检测太阳能板上的缺陷
检测流程:
- 三通道图分解成三张单通道图
- 筛选出灰度在指定范围内的区域并将每一个区域自己连接起来
- 选出好的区域和杂乱的区域
- 在整个图片上找,如果既不是好的区域,也不是杂乱的区域,那就是有问题的区域
* For the solar industry, a common problem is the damage of
* fingers of solar cells. This example shows how to
* extract the broken fingers using morphology.
*
* 一般放在程序的开始,将dev_update_window, dev_update_var, dev_update_pc全部设置成off,目的是减少在GUI更新耗费的时间。
* dev_update_window: default: on,指定算子返回的所有图标对象是否需要显示在活动的图形窗口。这个选项设置成off后,需要使用dev_display算子来显示。
* dev_update_var: default: on,指定变量窗口在程序指定过程中的行为,设置成off后变量在程序执行完之前都不会更新;设置为on变量窗口中的内容在每次有变量发生变化时都会改变
* dev_update_pc: default: on,指定程序在执行过程中pc(程序计数器)的行为
dev_update_off ()
* 关闭活动的图形窗口
dev_close_window ()
* 图片名变量
ImageName := 'solar_cell/solar_cell_'
* 读入图片,常用的图片格式的后缀可以不加,第一个参数是输出:读取到的图片,当读取了多个文件时是一个列表;第二个参数:文件路径,当需要读取多个文件时,以列表形式输入,例如:
* 同时读取两张图片,文件名分别为1.jpg和2.jpg
* read_image(Image, ['1', '2']
read_image (Image, ImageName + '01')
* 打开一个窗口大小保持图像比例的图像窗口,参数:
* Image 要显示的图像
* Row 新窗口左上角的行坐标
* Column 新窗口做商家的列坐标
* WidthLimit 宽度最大值,默认-1
* HeightLimit 高度最大值,默认-1
* WindowHandle 新的图形窗口的句柄
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
* 设置显示的字体 窗口句柄,大小,字体,是否加粗,是否倾斜
* 注意字体是否是已经在系统中安装有的
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* 设置在图像窗口上显示的各种元素的颜色,例如圈区域之类的
dev_set_color ('red')
* 设置区域的填充模式,margin仅显示轮廓,fill填满
dev_set_draw ('margin')
* 设置轮廓线宽
dev_set_line_width (2)
*
* 找出每张图上的缺陷区域
* For each image of a solar cell, extract defect areas
NumImages := 6
for Index := 1 to NumImages by 1
read_image (Image, ImageName + Index$'02')
* 将一张三通道图片分解为三张单通道图片
decompose3 (Image, ImageR, ImageG, ImageB)
* Segment dark regions (everything except the fingers) 分割出黑色区域(除了有特征的区域外的所有区域)
* 获取出满足阈值条件的图片区域,参数:传入图片,传出分割的区域,最小灰度,最大灰度
threshold (ImageR, Region, 0, 159)
* 计算一个区域的连接的组件,参数:传入区域,传出连接的组件
connection (Region, ConnectedRegions)
* Select good parts and clutter regions 筛选出好的部分和杂乱的部分
* 通过特征筛选区域, 参数:传入区域,传出选中的区域,传入需要核验的特征列表,特征是“和”还是“或”,特征的最小值列表,特征的最大值列表。区域范围上下限都包含。
* 筛选出满足条件:面积在3500-5000,宽度在130-300之间的区域(两边较窄的部分)
select_shape (ConnectedRegions, GoodSmallParts, ['area','width'], 'and', [3500,130], [5000,300])
* 筛选出满足条件:面积在6000-10000,宽度在350-550之间的区域(中间较宽的部分)
select_shape (ConnectedRegions, GoodLongParts, ['area','width'], 'and', [6000,350], [10000,550])
* 筛选出满足条件:宽度在350-550之间或 高度在900-1000或面积在0-100的区域
select_shape (ConnectedRegions, Clutter, ['width','height','area'], 'or', [900,900,0], [1000,1000,100])
* Regions that are neither good parts nor clutter contain broken fingers 既不是好的也不是杂乱的区域包含损坏的特征
* 找出两个区域的不同区域
* 连接域和好的小区域的不同
difference (ConnectedRegions, GoodSmallParts, Difference)
* 上面找出的不同和好的大区域的不同
difference (Difference, GoodLongParts, Difference)
* 上面找出的不同和杂乱区域的不同,剩下的就是坏的区域了
difference (Difference, Clutter, BrokenParts)
* 变换区域的形状, 参数:传入需要变换的区域,传出变换后的区域,传入变换类型为'rectangle1':与坐标轴平行,小的矩形框
shape_trans (BrokenParts, BrokenPartsTrans, 'rectangle1')
* Isolate the break for visualization 剔除坏的区域
* 用一个矩形的构造结构元素腐蚀指定区域,参数:传入区域,传出腐蚀后的区域,传入矩形的宽,矩形的高
* 腐蚀的依据是什么?
erosion_rectangle1 (BrokenParts, RegionErosion, 1, 25)
* 连接腐蚀后的区域
connection (RegionErosion, ConnectedBreaks)
* 对连接好的区域做变换,'outer_circle' :小的圈
shape_trans (ConnectedBreaks, Breaks, 'outer_circle')
* 用一个圆形的元素膨胀,参数:传入区域,传出膨胀后的区域,传入圆形的半径
dilation_circle (Breaks, Breaks, 6)
* Remove empty regions 移除空的区域
* (This could also be achieved with set_system('store_empty_region','false')
* 选择区域,传入区域,传出选择好的区域,特征是面积,特征关系是和,最小1,最大99999999
* 选择出面积在1-99999999的区域
select_shape (Breaks, Breaks, 'area', 'and', 1, 99999999)
* 计算出列表中元素的数量
* 算出有多少个破损块
count_obj (Breaks, CountBreaks)
*
* Display results of inspection 显示检查的结果
*
dev_display (Image)
dev_display (BrokenPartsTrans)
dev_display (Breaks)
*
if (CountBreaks == 0)
disp_message (WindowHandle, 'Cell OK', 'window', 12, 12, 'black', 'true')
else
disp_message (WindowHandle, 'Cell not OK', 'window', 12, 12, 'red', 'true')
endif
*
if (Index != NumImages)
* 显示继续执行的消息框,显示内容始终为"Click 'Run' to continue"
disp_continue_message (WindowHandle, 'black', 'true')
* 程序停止运行
stop ()
endif
* If only one defect is present, zoom in 如果只发现了一个缺陷,将缺陷放大显示
if (CountBreaks == 1)
* 在坐标(0, 610)打开一个300*300的黑色的窗口
dev_open_window (0, 610, 300, 300, 'black', WindowHandle1)
* 获取区域的面积和中心位置
area_center (Breaks, Area, Row, Column)
* 调整显示的图片
dev_set_part (Row[0] - 50, Column[0] - 50, Row[0] + 50, Column[0] + 50)
dev_display (Image)
dev_display (BrokenPartsTrans)
dev_display (Breaks)
stop ()
* 激活窗口
dev_set_window (WindowHandle1)
* 关闭窗口
dev_close_window ()
endif
endfor
常用的运算符:
- 赋值:
:=
- for循环
for start to end by step
...endfor
start end都会包含,步幅step可调整 - if语句
if
...endif
算子使用
-
threshold(Image, Region, MinGray, MaxGray)
应该怎样选取合适的阈值范围?可以在图形窗口看一下3d点图感受一下
原图:
3d点图:
-
erosion_rectangle1(Region, RegionErosion, Width, Height)
用一个矩形的结构元素腐蚀指定区域。- 什么是腐蚀?
- 腐蚀的作用是什么?
图像的取样和量化
取样:对坐标值进行数字化;
量化:对幅值进行数字化
数字图像处理方法分类:线性和非线性