Blob分析之check_blister.hdev

*这个例子展示了hancon 在制药行业的应用,目的检测自动封装的药丸对不对
*第一张图像作为参考图像,用来定位后续图像的胶囊的胶囊仓。用Blob分析分割的药丸并对进行分类
*这个实例中,用的最关键的东西是基于灰度的识别,操作
*This example demonstrates an application from the pharmaceutical
* industry. The task is to check the content of automatically filled
* blisters. The first image (reference) is used to locate the chambers
* within a blister shape as a reference model, which is then used to
* realign the subsequent images along to this reference shape. Using
* blob analysis the content of each chamber is segmented and finally
* classified by a few shape features.
* 关闭窗体
dev_close_window ()
*关闭更新
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')
*设置线宽
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)
*显示图像
dev_display (Image1)
*阈值分割
threshold (Image1, Region, 90, 255)
*显示图像
dev_display (Region)
*变换形状
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)
*仿射变换图像到参考图像
affine_trans_image (ImageOrig, Image2, HomMat2D, 'constant', 'false')
*生成空对象
gen_empty_obj (Chambers)
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
*仿射变换区域到参考区域
affine_trans_region (Blister, Blister, HomMat2D, 'nearest_neighbor')
*求差集
difference (Blister, Chambers, Pattern)
*联合区域,与concat不同的是,union是和几为一,原来的对象没有了,而concat只是组成一个集合,原来的对象还按顺序放着
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)
    *根据平均和标准偏差分析进行阈值分割
    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
    *胶囊数量。
    count_obj (Chambers, Number)
    *生成空的错误药片/胶囊-----共有两种错误:错装和漏装
    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)
        disp_continue_message (WindowHandle, 'black', 'true')
    endif
    stop ()
endfor

posted @ 2020-07-31 09:24  懒树懒  阅读(288)  评论(0)    收藏  举报