halcon例程解析:检查相同药片——check_blister

原文介绍:

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.

这个例子演示了一个制药行业的应用程序。任务是检查自动填充的水泡的内容。第一幅图像(参考)用于定位气泡形状内的腔室作为参考模型,然后使用该参考模型重新排列随后的图像以达到该参考形状。采用斑点分析法对每个腔体的内容进行分割,最后通过一些形状特征对其进行分类。

1. 效果展示

利用一个标准图像做模板,检测药片的有无、错误

模板图与检测图
在这里插入图片描述
在这里插入图片描述
结果
在这里插入图片描述

2. 思路分析

  1. 利用参考图建立每个药片的位置模型
    1. 分割出前景区域
    2. 计算其旋转,刚性映射变换摆正
    3. 确定目标区域,并计算得到其中心与偏转角,用于对检测图像进行刚性矫正
  2. 矫正检测图像,确定检测区域
    1. 分割出前景区域
    2. 计算其旋转、中心
    3. 利用参考图的中心与偏角对检测区域进行刚性变换
    4. 利用模板区域分割出检测区域
  3. 对检测区域进行定性分析,分类

2.1 利用参考图建立每个药片的位置模型

* 取第一个通道数据
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)

* 仿射变换,摆正图像
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)

* 组合区域
union1 (Chambers, ChambersUnion)

* 再次计算偏角和中心,这用于对后边待检测图像进行矫正
orientation_region (Blister, PhiRef)
PhiRef := rad(180) + PhiRef
area_center (Blister, Area2, RowRef, ColumnRef)

在这里插入图片描述

2.2 矫正检测图像

* 在待检测图像中分割出前景区域
threshold (Image, Region, 90, 255)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 9999999)
shape_trans (SelectedRegions, RegionTrans, 'convex')

* 对图像进行仿射变换,向参考图像矫正
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')

在这里插入图片描述
在这里插入图片描述

2.3 分割检测区域并优化

* 依靠模板区域分割出检测区域
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')

在这里插入图片描述

2.4 对每个位置分类

* 计算检测区域的数量
count_obj (Chambers, Number)
gen_empty_obj (WrongPill)
gen_empty_obj (MissingPill)

* 检测位置面积为0表示缺失,面积或者最小值不正常说明错误
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

3. 完整代码

* 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)
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)
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)
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值