官方例程学习分享-Check_Blister

需求+思路

  • 产品需求:
  •     5*3的胶囊,检测胶囊是否装错(用阈值去判定)或者漏装(用个数去判定)
    

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

  • 思路分析:整一块药片的大小是固定的,只不过是来料的位置和角度有偏差,且无背景干扰,应该是用吸嘴去吸附产品
  •      用仿射变换+阈值分割即可进行检测
    
  • 实现步骤:
  •      ①选择一张作为参考的标准图像,但这张图像可能并不一定正正方方,所以要:对感兴趣的区域跟0°进行 仿射变换 成一个正方的姿态(得到:此姿态的中心坐标和角度)
    
  •      ②在此姿态上,创建一个包含15个矩形区域的元组,目的:把来料通过交集的方式单独取下每颗胶囊进行分析
    
  •      ③读取来料产品,通过阈值分割粗定位到来料,获取中心坐标,用orientation_region定个方向
    
  •      ④通过仿射变换为参考图的姿态,这样就能够跟创建的15个矩形元组坐标对应得上
    
  •      ⑤通过阈值分割+开闭运算把15个胶囊先扣下来,为region array(这里的个数代表有无漏装)
    
  •      ⑥一一遍历元组15个矩形,通过求交集方式,扣出来料产品中每一颗胶囊,
    
  •      ⑦对胶囊的面积和最小最大灰度进行判定,得出是否装错
    

实现代码和备注如下

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')
* 定位region的填充方式,margin为边缘,fill为整个区域,以下整个程序按照这个设定去显示
dev_set_draw ('margin')
* 因为上面选的是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.

*访问多通道图像中的某个通道,R:1  G:2  B:3。 一张图最多有24个通道
*这个算子与rgb1_to_gray(x,a)和rgb3_to_gray(r,g,b,a)效果不同
access_channel (ImageOrig, Image1, 2)
threshold (Image1, Region, 90, 255)
*改变一个区域的形状:去除掉一些零零碎碎的区域
shape_trans (Region, Blister, 'convex')
*给区域定个方向,Phi是用于后面的变换矩阵需要
orientation_region (Blister, Phi)
*计算区域的面积和区域中心坐标
area_center (Blister, Area1, Row, Column)
*从点和角度去计算得出一个精确的仿射矩阵(输入“源”的坐标和角度,以及“目标”的坐标和角度)
vector_angle_to_rigid (Row, Column, Phi, Row, Column, 0, HomMat2D)
*把仿射2D矩阵应用图像当中
*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:创建任意方向的矩形/参数是填矩形长高的一半;gen_rectangle1:创建与坐标轴平行的矩形
        gen_rectangle2 (Rectangle, Row, Column, 0, 64, 30)
        *连接两个元组/区域,注意:union1/2是融合区域,个数就变少了
        concat_obj (Chambers, Rectangle, Chambers)
    endfor
endfor
*把仿射2D矩阵应用到区域当中
affine_trans_region (Blister, Blister, HomMat2D, 'nearest_neighbor')
*计算两个区域的不同
difference (Blister, Chambers, Pattern)
*返回所有区域的并集->把整个元组返回出来
union1 (Chambers, ChambersUnion)
*把经过仿射变换后的Blister定个方向
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)
    * 把仿射2D矩阵应用到Image中
    affine_trans_image (Image, ImageAffineTrans, HomMat2D, 'constant', 'false')
    * 
    * Segment pills
    * 按照union出来的区域把感兴趣的区域裁剪出来
    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)
        * 计算两个区域的交集,Chamber和Pills都是region array
        * 这一步骤:把每个pill单独拿出来进行分析
        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
            * 如果area=0说明漏装胶囊
            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)
    * 这里的Pills的每个元素都是margin, 所以显示出来的边,不会是区域覆盖原图像
    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
    * 创建长度为length的常量型元组
    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

产品处理结果如下图

在这里插入图片描述在这里插入图片描述分析有不到位的,请各位点评指正~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值