Halcon:药品缺陷检测

图像处理结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要思想:
Blob +特征
Blob:使用采集图像,做药片板的定位,药片格子的定位。然后将待测图像旋转到模板图像的区域。
就可以直接使用药片格子的区域了。将药片格子区域和每次筛选出的药片区域求交集。
特征:筛选交集的区域,如果区域<3800或者最小灰度值<60,错误药片+1。如果区域为空,说明空药片+1.

*Blob分析+特征的方法
*环光反射的方式
*1.采集图像
*关闭窗口
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’)
*设置线宽3像素
dev_set_line_width (3)
*2.定位算法(求标准位置,用的是Blob分析)
*原本是彩色图像,获取其中的一个灰度图像,1代表的是第一通道图像,B通道图像。1是B,2是G,3是R
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’)
*3.将药丸区域人工的设定出来
*获取一个空的区域
gen_empty_obj (Chambers)
*代表列,从0-4,说明一列有5个
for I := 0 to 4 by 1
*代表每一列之间相差大约70个像素。左上角第一个区域的列坐标为70
Row := 88 + I * 70
*代表行,从0-2,说明一行有3个
for J := 0 to 2 by 1
*代表每一行之间相差大约150个像素。左上角第一个区域的行坐标为163
Column := 163 + J * 150
*获取一个区域,中心坐标是 Row, Column,长度是64,宽度是30
gen_rectangle2 (Rectangle, Row, Column, 0, 64, 30)
*将该区域添加到一个容器里面,这个容器代表的所有药丸区域
concat_obj (Chambers, Rectangle, Chambers)
endfor
endfor
*Chambers就是药丸区域的参考区域
*4.获取药丸的标准区域
*获取之前整个药丸板的区域做对应的变换
affine_trans_region (Blister, Blister, HomMat2D, ‘nearest_neighbor’)
*将药丸板和药丸区域做差值,获取到的就是空的药丸板区域
difference (Blister, Chambers, Pattern)
*药丸的区域之前是分开的,现在联合起来
union1 (Chambers, ChambersUnion)
*获得药丸板区域的角度
orientation_region (Blister, PhiRef)
*角度+180°的原因是为了得到正值
PhiRef := rad(180) + PhiRef
*得到转正区域的坐标
area_center (Blister, Area2, RowRef, ColumnRef)
*上面从affine_trans_region到area_center这些代码
*是为了得到模板药丸区域的角度,重心坐标。有些是不用的。例子中有,就保留对应的

  • 5.缺陷检测。
    *共6张图像,做对应的检测
    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’)
    • 计算角度
      orientation_region (RegionTrans, Phi)
      *获取中心坐标
      area_center (RegionTrans, Area3, Row, Column)
      *这一步要注意:之前上面的适合水平的做变换。但实际上使用的时候,还是有些微的偏差。
      *所以和上述第3步计算出的角度,以及坐标做变换。这样上面求出的药丸位置就可以直接使用的了。
      vector_angle_to_rigid (Row, Column, Phi, RowRef, ColumnRef, PhiRef, HomMat2D)
      *图像变换
      affine_trans_image (Image, ImageAffineTrans, HomMat2D, ‘constant’, ‘false’)
      *6.药片分割

    • 扣取药丸区域
      reduce_domain (ImageAffineTrans, ChambersUnion, ImageReduced)
      *将彩色图像拆分成R,G,B的图像
      decompose3 (ImageReduced, ImageR, ImageG, ImageB)
      *根据局部的均值和方差二值化,得到其中较暗的区域
      *也可以使用threshold进行设定
      var_threshold (ImageB, Region, 7, 7, 0.2, 2, ‘dark’)
      *区域分割
      connection (Region, ConnectedRegions0)
      *闭运算,放大选择的区域
      closing_rectangle1 (ConnectedRegions0, ConnectedRegions, 3, 3)
      *填充区域
      fill_up (ConnectedRegions, RegionFillUp)
      *筛选其中区域>1000像素的区域,是为了筛除掉小的无关区域
      select_shape (RegionFillUp, SelectedRegions, ‘area’, ‘and’, 1000, 99999)
      *圆的开运算,去除小的噪点
      opening_circle (SelectedRegions, RegionOpening, 4.5)
      *将区域进行分割
      connection (RegionOpening, ConnectedRegions)
      *筛选其中区域>1000像素的区域,为了筛选真正的药丸区域
      select_shape (ConnectedRegions, SelectedRegions, ‘area’, ‘and’, 1000, 99999)
      *获取凸性区域:区域内任意两点的连线,都在区域内部。区域为凸性
      shape_trans (SelectedRegions, Pills, ‘convex’)

    • 计算药片个数
      count_obj (Chambers, Number)
      *放置错误药片
      gen_empty_obj (WrongPill)
      *放置丢失区域
      gen_empty_obj (MissingPill)
      *从1开始,计算药片情况
      for I := 1 to Number by 1
      *选择第一个区域
      select_obj (Chambers, Chamber, I)
      *计算药片区域Pills和放药片的区域Chamber的交叉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)
      *如果区域<3800或者最小灰度值<60,说明放置的不正确,错误药片+1。
      *也可以只判断面积
      concat_obj (WrongPill, Pill, WrongPill)
      endif

      else
      *说明没有药片,那该区域就丢失了药片,计数+1
      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)
      *存在丢失药片或者错误药片,那么该次药片放置时NG的
      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)

对应示例程序:
check_blister.hdev

  • 1
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值