图像处理(二)

halcon例程 inspect_solar_fingers.hdev 注释

Halcon中的几个窗口:

  1. 图形窗口
    左上角坐标为(0,0),x轴向下延伸,y轴向右延伸,z轴代表灰度
  2. 变量窗口
  3. 程序窗口

检测太阳能板上的缺陷

检测流程:

  1. 三通道图分解成三张单通道图
  2. 筛选出灰度在指定范围内的区域并将每一个区域自己连接起来
  3. 选出好的区域和杂乱的区域
  4. 在整个图片上找,如果既不是好的区域,也不是杂乱的区域,那就是有问题的区域
* 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

常用的运算符:

  1. 赋值::=
  2. for循环 for start to end by step ... endfor
    start end都会包含,步幅step可调整
  3. if语句 if...endif

算子使用

  1. threshold(Image, Region, MinGray, MaxGray)
    应该怎样选取合适的阈值范围?可以在图形窗口看一下3d点图感受一下
    原图:

    3d点图:

  2. erosion_rectangle1(Region, RegionErosion, Width, Height)
    用一个矩形的结构元素腐蚀指定区域。

    1. 什么是腐蚀?
    2. 腐蚀的作用是什么?

图像的取样和量化

取样:对坐标值进行数字化;
量化:对幅值进行数字化

数字图像处理方法分类:线性和非线性

原文地址:https://www.cnblogs.com/yutou2016/p/11052887.html