图片资源
链接:https://pan.baidu.com/s/1jHURp4MQ4ex-dfeURZ6OhQ
提取码:d0hg
处理流程
1、模板图片角度计算与校正 保存校正后的角度与中心点
2、计算药片处理区域
3、循环处理图片,重新获取角度与中心点,做仿射变换
4、药片区域连通域获取(局部二值,闭运算,开运算)
5、药片分类
6、统计个数与显示结果
完整代码
***** 1、加载图片与显示设置**************
dev_close_window ()
dev_update_off ()
read_image (ImageOrig, './img/blister_reference.png')
dev_open_window_fit_image (ImageOrig, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'sans', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (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')
***** 3、计算矩形框(15个 药品的位置矩形框)**************
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
***** 4、计算模板矩形框旋转后的绝对角度 (旋转目标角度,旋转中心点)**************
* 旋转外框
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)
**** 循环分析图片 ********************************************************************
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)
**** b、旋转处理图片 *****************************
* 获取外框凸包区域
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')
*
**** c、药片区域获取 *****************************
* 缩小处理区域
reduce_domain (ImageAffineTrans, ChambersUnion, ImageReduced)
* RGB图片抽取
decompose3 (ImageReduced, ImageR, ImageG, ImageB)
* 局部二值化 7*7 局部区域,0.2 刻度 2:绝对阈值
var_threshold (ImageB, Region, 7, 7, 0.2, 2, 'dark')
dev_display (Region)
* 连通域分析
connection (Region, ConnectedRegions0)
* 闭运算矩形(链接药片内部)
closing_rectangle1 (ConnectedRegions0, ConnectedRegions, 3, 3)
* 填充内部区域
fill_up (ConnectedRegions, RegionFillUp)
dev_clear_window ()
dev_display (RegionFillUp)
* 筛选连通域 (筛选掉小区域)
select_shape (RegionFillUp, SelectedRegions, 'area', 'and', 1000, 99999)
dev_clear_window ()
dev_display (SelectedRegions)
* 开运算(断开多余部分)
opening_circle (SelectedRegions, RegionOpening, 4.5)
dev_clear_window ()
dev_display (RegionOpening)
* 连通域分析
connection (RegionOpening, ConnectedRegions)
* 再次筛选 连通域 (筛选掉小区域)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 1000, 99999)
* 凸包连通域为 药片连通域
shape_trans (SelectedRegions, Pills, 'convex')
dev_clear_window ()
dev_display (ImageAffineTrans)
dev_display (Pills)
**** d、药片分类(检测) *****************************
* 统计连通域个数
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)
* 蓝色图片中,药片区域 灰度最小最大值,0 高于0的百分比
min_max_gray (Pill, ImageB, 0, Min, Max, Range)
* 面积小于 3800 说明药片不存在 min < 60说明有暗区 药片出现错误
if (Area < 3800 or Min < 60)
* 统计错误药片
concat_obj (WrongPill, Pill, WrongPill)
endif
else
* 统计丢失药片
concat_obj (MissingPill, Chamber, MissingPill)
endif
endfor
**** E、统计OK,错误,丢失个数 *****************************
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)
* NG
disp_message (WindowHandle, 'Not OK', 'window', 12, 12 + 600, 'red', 'true')
else
* OK
disp_message (WindowHandle, 'OK', 'window', 12, 12 + 600, 'forest green', 'true')
endif
**** F、显示个数 *****************************
Message := '# 药片OK数量: ' + (NumberP - NumberWP)
Message[1] := '# 药片错误 : ' + NumberWP
Message[2] := '# 药片丢失:: ' + 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