halcon胶囊质检-详解

halcon 胶囊检测

代码所在位置:halcon软件,点击文件,浏览hdevelop实例程序,check_blister.hdev.
实例所在位置

项目代码分析

这个例子演示了一个来自制药公司的应用行业。任务是检查内容的自动填充胶囊。第一幅图像(参考)用于定位腔室在一个泡内的形状作为参考模型,这是然后使用对齐后续的图像沿着这个参考形状。使用 blob分析对每个箱体的内容进行分段并最终根据一些形状特征分类。
关闭窗口,读取原始胶囊的图片,根据胶囊图片的大小打开图片。

dev_close_window ()
*将dev_update_pc, dev_update_var and dev_update_window设置为Off。设置程序刷新关闭
dev_update_off ()
read_image (ImageOrig, 'blister/blister_reference')
dev_open_window_fit_image (ImageOrig, 0, 0, -1, -1, WindowHandle)

在这里插入图片描述

设置显示的字体,设置填充方式为边缘填充方式,设置绘制的线条的宽度。

set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
*设置填充模式为边缘填充模式
dev_set_draw ('margin')
*定义输出的线宽为3
dev_set_line_width (3)

以下代码我们要做一个图案把里面的腔室切出来,对于后续的胶囊处理更加方便。注释在代码里面。

* In the first step, we create a pattern to cut out the chambers in the
* subsequent blister images easily.
*提取色彩通道 这里是提取灰度图图像
access_channel (ImageOrig, Image1, 1)
threshold (Image1, Region, 90, 255)
*每个区域的凸性区域
shape_trans (Region, Blister, 'convex')
*得到和输入区域具有相同方向的椭圆
orientation_region (Blister, Phi)
*区域和区域中心 中心分别计算所有行列坐标的平均值
area_center (Blister, Area1, Row, Column)
*模板匹配算子 从点和角度计算刚性仿射变换
*前三个参数 原始点的坐标原始点的角度,转换点的坐标和角度,最后一个为输出参数
*输出转换矩阵
vector_angle_to_rigid (Row, Column, Phi, Row, Column, 0, HomMat2D)
*对XLD轮廓进行任意仿射2D变换(缩放、旋转、平移、倾斜)
affine_trans_image (ImageOrig, Image2, HomMat2D, 'constant', 'false')

在这里插入图片描述

下面的代码是一个循环,主要是找出,排列的5行3列的胶囊。对于轮廓的查找绘制的轮廓咋上一段代码中已经定义过。

*创建一个空的object 类似类的实例化,防止空引用异常
gen_empty_obj (Chambers)
*该循环的作用是 遍历图片上的的5行3列的胶囊,并绘制一个矩形
for I := 0 to 4 by 1
    Row := 88 + I * 70
    for J := 0 to 2 by 1
        Column := 163 + J * 150
        *创建一个任意方向的矩形 参数:输出的矩形,中心点的坐标值,与水平方向的夹角,矩形的宽高
        gen_rectangle2 (Rectangle, Row, Column, 0, 64, 30)
        *连接两个对象,输入对象,输出对象,连接后的区域
        concat_obj (Chambers, Rectangle, Chambers)
    endfor
endfor

在这里插入图片描述
以下代码是将上一步找到的即15个胶囊的所有区域合并成为一个区域。

*根据二维矩阵中的参数进行仿射变换
affine_trans_region (Blister, Blister, HomMat2D, 'nearest_neighbor')
*计算两个边界的差
difference (Blister, Chambers, Pattern)
*把所有的输入区域合并为一个区域
union1 (Chambers, ChambersUnion)

在这里插入图片描述
下面的代码是通过循环读取每一张图像,然后进行处理找出每张图像种的胶囊的区域,为下面的统计胶囊质量的代码做准备。

*得到和输入区域具有相同方向的椭圆
orientation_region (Blister, PhiRef)
PhiRef := rad(180) + PhiRef
*区域中心
area_center (Blister, Area2, RowRef, ColumnRef)
* 
* 
* Each image read will be aligned to this pattern and reduced to the area of interest,
* which is the chambers of the blister
*读取的每个图像都将与该模式对齐,并缩小到感兴趣的区域,就是水泡的腔室
Count := 6
for Index := 1 to Count by 1
    read_image (Image, 'blister/blister_' + Index$'02')
    threshold (Image, Region, 90, 255)
    connection (Region, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 9999999)
    shape_trans (SelectedRegions, RegionTrans, 'convex')
    * 
    * Align pattern along blister of image
    orientation_region (RegionTrans, Phi)
    area_center (RegionTrans, Area3, Row, Column)
    vector_angle_to_rigid (Row, Column, Phi, RowRef, ColumnRef, PhiRef, HomMat2D)
    affine_trans_image (Image, ImageAffineTrans, HomMat2D, 'constant', 'false')
    * 
    * Segment pills
    *获得特定区域的图像 参数:输入的图像,输入的区域,输出的图像
    reduce_domain (ImageAffineTrans, ChambersUnion, ImageReduced)
    *将三通道的图像转换为三张图像
    decompose3 (ImageReduced, ImageR, ImageG, ImageB)
    *局部阈值化算子 基于均值和方差的阈值化 
    *参数:输入输出图片,滤波的掩码,标准差乘数因子,设置的绝对阈值,区域阈值的明暗程度
    *先用7*7的掩膜在图像上组个像素游走,用原图的像素和当前像素的灰度均值对比,
    *当原图的值低于掩膜的值的时候将该区域分割出来。
    var_threshold (ImageB, Region, 7, 7, 0.2, 2, 'dark')
    *联通区域
    connection (Region, ConnectedRegions0)
    *取最小外接矩形
    closing_rectangle1 (ConnectedRegions0, ConnectedRegions, 3, 3)
    *填充区域内的孔洞
    fill_up (ConnectedRegions, RegionFillUp)
    *根据面积找出区域
    select_shape (RegionFillUp, SelectedRegions, 'area', 'and', 1000, 99999)
    *开运算 去掉多余的小尾巴
    opening_circle (SelectedRegions, RegionOpening, 4.5)
    connection (RegionOpening, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 1000, 99999)
    shape_trans (SelectedRegions, Pills, 'convex')

在这里插入图片描述
以下的代码是将每一张图片种的所有胶囊的轮廓区域提取出来,并计算正常区域的、错误区域的、没找到轮廓区域的胶囊的数量,并在后面计数统计,显示出来。

* Classify segmentation results and display statistics
    *对分割结果进行分类并显示统计数据
    *这里的number是15 表示的是15个区域
    *count_obj是用来计算输入区域中连通域的个数
    count_obj (Chambers, Number)
    *创建一个新的object
    gen_empty_obj (WrongPill)
    gen_empty_obj (MissingPill)
    for I := 1 to Number by 1
        *从区域中选择一个区域
        select_obj (Chambers, Chamber, I)
        *获得区域的交集 胶囊和小方格的交集
        intersection (Chamber, Pills, Pill)
        *参数:被测区域,被测区域的面积,被测区域中心的行索引,列索引
        area_center (Pill, Area, Row1, Column1)
        if (Area > 0)
            *提取所在区域最大最小的灰度值
            min_max_gray (Pill, ImageB, 0, Min, Max, Range)
            if (Area < 3800 or Min < 60)
                *连接两个对象,将两个区域组合到一起
                concat_obj (WrongPill, Pill, WrongPill)
            endif
        else
            concat_obj (MissingPill, Chamber, MissingPill)
        endif
    endfor
    * 
    dev_clear_window ()
    dev_display (ImageAffineTrans)
    dev_set_color ('forest green')
    *对三种区域进行计数
    count_obj (Pills, NumberP)
    count_obj (WrongPill, NumberWP)
    count_obj (MissingPill, NumberMP)
    dev_display (Pills)
    if (NumberMP > 0 or NumberWP > 0)
        *出现问题的区域,进行一下的显示
        disp_message (WindowHandle, 'Not OK', 'window', 12, 12 + 600, 'red', 'true')
    else
        disp_message (WindowHandle, 'OK', 'window', 12, 12 + 600, 'forest green', 'true')
    endif
    * 显示正确的胶囊和错误的胶囊和找不到的胶囊
    Message := '# Correct pills: ' + (NumberP - NumberWP)
    Message[1] := '# Wrong pills  :  ' + NumberWP
    Message[2] := '# Missing pills:  ' + NumberMP
    * 
    *初始化矩阵
    Colors := gen_tuple_const(3,'black')
    if (NumberWP > 0)
        Colors[1] := 'red'
    endif
    if (NumberMP > 0)
        Colors[2] := 'red'
    endif
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    dev_set_color ('red')
    dev_display (WrongPill)
    dev_display (MissingPill)
    if (Index < Count)
        *在荧幕上显示暂停程序继续操作的信息,'true'参数文字在白色框子里面显示。
        disp_continue_message (WindowHandle, 'black', 'true')
    endif
    stop ()
endfor

程序执行结果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值