halcon例程解析:数回收箱箱里的瓶子——check_bottle_crate
This example counts bottles in bottle crates of returned empties. With diffuse front light, correctly inserted bottles can be segmented relatively easy with a simple thresholding operation, followed by some basic morphology operations. Bottles inserted upside-down are also detected and displayed in orange, while across lying bottles or big objects are marked as clutter and produce a warning.
这个例子数的是回收箱中的空瓶子。使用漫射前光,正确插入的瓶子可以相对容易地分割,只需简单的阈值操作,然后进行一些基本的形态学操作。倒插的瓶子也能被检测到,并显示为橙色,而横放的瓶子或大物体则被标记为杂物,并产生警告。
1. 效果展示
2. 思路分析
这个问题比较简单,不需要太复杂的算法,只通过亮度等进行阈值分割、面积圆度等即可
经过漫射光的打光后,在表面的瓶口、瓶底及瓶身比较亮,当然回收箱的边缘也比较亮,这里我们只要通过亮度阈值分割;区域面积、宽、高、圆度即可区分出正常瓶子、数量、异物等
- 阈值分割出背景区域
- 阈值分割出瓶子区域
- 作差,优化瓶子区域
- 依靠宽、高提取大的异物;并做开运算去除箱体边缘等影响
- 有效区域减去异物
- 依靠宽、高去除其他影响,并填充剩余区域
- 依靠圆度分割出瓶子区域
- 依靠半径检测出较大的圆,即为倒放的瓶子
- 结果处理
2.1 初步检出瓶子区域
* 分割出背景区域
threshold (Image, BackgroundRegion, 50, 130)
opening_circle (BackgroundRegion, BackgroundRegion, 3.5)
* 分割出有效区域
threshold (Image, Region, 85, 255)
* 作差,优化有效区域
difference (Region, BackgroundRegion, Region)
connection (Region, ConnectedRegions)
2.2 检测较大的异物
* 分割出较大的异物
select_shape (ConnectedRegions, Clutter, ['width','height'], 'or', [100,100], [500,400])
opening_circle (Clutter, Clutter, 8.5)
* 作差减去异物
difference (ConnectedRegions, Clutter, Region)
connection (Region, ConnectedRegions)
2.3 依靠宽、高去除其他影响,并填充剩余区域
* 有效区域的宽、高范围
select_shape (ConnectedRegions, Candidates, ['width','height'], 'and', [25,25], [100,100])
* 填充区域
fill_up (Candidates, FilledCandidates)
* 使用开运算去除小区域
opening_circle (FilledCandidates, FilledCandidates, 15.5)
2.4 依靠圆度分割出瓶子区域
* 圆度分割瓶子区域
select_shape (FilledCandidates, RoundCandidates, 'circularity', 'and', 0.87, 1)
* 依靠半径筛选大区域
select_shape (RoundCandidates, BigBottles, 'max_diameter', 'and', 75, 99999)
3. 全部代码
* This example counts bottles in bottle crates of returned empties.
* With diffuse front light, correctly inserted bottles can
* be segmented relatively easy with a simple thresholding operation,
* followed by some basic morphology operations.
* Bottles inserted upside-down are also detected and displayed
* in orange, while across lying bottles or big objects are
* marked as clutter and produce a warning.
*
* init
get_system ('store_empty_region', StoreEmptyRegion)
set_system ('store_empty_region', 'false')
read_image (Image, 'bottles/bottle_crate_01')
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_update_off ()
dev_set_draw ('margin')
* main loop
for Index := 1 to 24 by 1
read_image (Image, 'bottles/bottle_crate_' + Index$'.02')
* extract background
threshold (Image, BackgroundRegion, 50, 130)
opening_circle (BackgroundRegion, BackgroundRegion, 3.5)
* extract bottle reflections
threshold (Image, Region, 85, 255)
difference (Region, BackgroundRegion, Region)
connection (Region, ConnectedRegions)
* large reflections are judged as clutter
select_shape (ConnectedRegions, Clutter, ['width','height'], 'or', [100,100], [500,400])
opening_circle (Clutter, Clutter, 8.5)
difference (ConnectedRegions, Clutter, Region)
connection (Region, ConnectedRegions)
* ignore noise regions
select_shape (ConnectedRegions, Candidates, ['width','height'], 'and', [25,25], [100,100])
fill_up (Candidates, FilledCandidates)
opening_circle (FilledCandidates, FilledCandidates, 15.5)
* only 'round' reflections are from bottles
select_shape (FilledCandidates, RoundCandidates, 'circularity', 'and', 0.87, 1)
select_shape (RoundCandidates, BigBottles, 'max_diameter', 'and', 75, 99999)
* display results
dev_set_shape ('ellipse')
count_obj (RoundCandidates, NumBottles)
count_obj (Clutter, NumClutter)
dev_display (Image)
dev_set_line_width (5)
dev_set_color ('lime green')
dev_display (RoundCandidates)
dev_set_color ('goldenrod')
dev_display (BigBottles)
dev_set_color ('red')
dev_display (Clutter)
dev_set_shape ('original')
disp_message (WindowHandle, NumBottles + ' bottles found.', 'window', 12, 12, 'black', 'true')
if (NumClutter > 0)
disp_message (WindowHandle, 'Warning! Clutter detected!', 'window', 40, 12, 'red', 'true')
endif
if (Index < 24)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
* restore original system settings
set_system ('store_empty_region', StoreEmptyRegion)