重点先说
免得耽误大家时间。本文重点就是通过画出 候选区域和扫描线来辅助定位问题。没有对查找参数做说明,可以通过这2个方法尽快找到参数不合理地方。
文中有不合理之处,欢迎大家批评指正
问题发现
一个条码非常清晰的图片读不出码,清晰到我肉眼都可以解码的图片,牛逼的Halcon没理由读不出
条码局部放大图片,可以看到非常清晰,大家可以尝试Halcon在这个图片上读码是否能找到码
问题分析
这个条码用手机摄像头很容易扫出来,说明条码本身没问题。刚开始怀疑条码的查找参数设置有问题,尝试修改参数,但是均没有效果。一头雾水,看不到Halcon 内部的执行机制,现在急切需要知道问题在哪。无耐去找Halcon 读码的示例程序,发现了一个 barcode_typical_cases.hdev。此示例程序提供了一些在读码异常时的一些调试技巧,大家可以看看。示例也强调:我们需要找到在读码的哪一步出错了。可以通过一些中间结果来辅助定位问题。我们可以在以下2个阶段来获取中间结果 1.检查候选区域 2检查扫描线。
候选区域 和 扫描线不做过多解释就按照字面理解吧,
1.画出候选区域
尝试将候选区域画出来看看,看看图片上条码是否在候选区域里,如果不在候选区域里那还找个嘚。
通过上面图可以看出,有4几个红色区域,我们关注的条码在候选区域内,这说明候选区域没大问题。读不出来肯定是别的问题。但是这里得插一嘴,这查找参数似乎不太合理,上面有2,3小区域显然不是查找区域。这个留给你们来看看怎么优化。
2.尝试画出条码
扫面线来看看 是否有问题
扫描线没啥问题,但是大家注意看看箭头的指向的那2个线,被扫描进来了,而且线条与条码的肥瘦非常相近,不会是这个影响了条码识别吧。同时 通过 get_bar_code_result (BarCodeHandle, 0, 'status', Status),Status='edges: not enough edges for a start, a stop and at least one data character. Possible saturation of gray values.' 提示没有找到开始和结束字符。
到这里我已经严重怀疑是条码前后那2个黑色线框,如果真如此,那Halcon 在条码读取这块确实考虑不周全。下一步就是尝试将那个边框给去除了,看看是否能读到码,用到的都是经典方法,threshold,connection,select_shape,将框的区域填充成255 白色。
尝试读取 OK了!!!!!
到此 问题解决。解决思路就是候选区域去除边框影响
程序代码
主程序
read_image (Image, 'C:/Users/Administrator/Desktop/code5.jpg')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
*图像处理去除边框影响,主要通过区域面积来筛选剔除区域,通过长宽也行
threshold(Image, Region, 0, 150)
connection(Region, ConnectedRegions)
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 99999999)
dilation_rectangle1(SelectedRegions,RegionDilation, 5, 5)
overpaint_region(Image,RegionDilation, 255, 'fill')
select_shape(ConnectedRegions, SelectedRegions2, 'height', 'and', 300, 99999999)
dilation_rectangle1(SelectedRegions2,RegionDilation2, 5, 5)
*overpaint_region(Image,RegionDilation, 255, 'fill')
gen_rectangle1 (Rectangle, 0, 0, 1947, 2933)
reduce_domain (Image, Rectangle, Image)
* crop_domain (ImageReduced, Image)
*优化条码图像
emphasize (Image, Image, 3, 3, 1)
scale_image_range (Image, ImageScaled, 30, 220)
*创建条码模型
create_bar_code_model ([], [], BarCodeHandle)
*设置解码参数
set_bar_code_param (BarCodeHandle, 'element_size_min', 2)
set_bar_code_param (BarCodeHandle, 'element_size_max',35)
set_bar_code_param (BarCodeHandle,'check_char','present')
set_bar_code_param (BarCodeHandle,'check_char','absent')
set_bar_code_param (BarCodeHandle, 'persistence', 1)
set_bar_code_param (BarCodeHandle, 'num_scanlines', 10)
set_bar_code_param (BarCodeHandle, 'start_stop_tolerance', 'high')
set_bar_code_param (BarCodeHandle, 'orientation', 0)
set_bar_code_param (BarCodeHandle, 'orientation_tol', 40)
set_bar_code_param (BarCodeHandle, 'element_height_min', 50)
find_bar_code (Image, SymbolRegions1, BarCodeHandle, ['Code 128'], BarCodeStrings)
get_bar_code_param (BarCodeHandle, 'element_size_min', GenParamValues)
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'symbol_regions')
get_bar_code_result (BarCodeHandle, 'all', 'decoded_types', BarCodeResults)
get_bar_code_result (BarCodeHandle, 0, 'status', Status)
get_bar_code_result (BarCodeHandle, 0, 'status_id', StatusID)
dev_display (Image)
disp_bar_code_candidates(BarCodeHandle,WindowHandle,NumberCandidates)
disp_bar_code_scanlines (BarCodeHandle, WindowHandle)
* disp_message (3600, BarCodeResults + '码:' + BarCodeStrings, 'image', 20, 20, 'black', 'true')
*清除条码模型
clear_bar_code_model (BarCodeHandle)
stop ()
disp_bar_code_candidates 候选区域显示代码
参照Halcon 例程 barcode_typical_cases.hdev
get_bar_code_object (Candidates, BarCodeHandle, 'all', 'candidate_regions')
count_obj (Candidates, NumberCandidates)
if (NumberCandidates == 0)
disp_message (WindowHandle, 'No candidates found', 'window', 32, 12, 'red', 'true')
else
dev_set_color ('magenta')
dev_display (Candidates)
disp_message (WindowHandle, 'Candidates: ' + NumberCandidates, 'window', 52, 12, 'magenta', 'true')
endif
return ()
disp_bar_code_scanlines 扫描线显示代码
参照Halcon 例程 barcode_typical_cases.hdev
*
get_bar_code_result (BarCodeHandle, 'all', 'decoded_types', DecodedTypes)
if (|DecodedTypes| == 0)
get_bar_code_object (AllScanlines, BarCodeHandle, 'all', 'scanlines_all')
dev_set_color ('red')
dev_display (AllScanlines)
disp_message (WindowHandle, 'No valid scanlines found', 'window', 72, 12, 'red', 'true')
else
get_bar_code_object (ValidScanlines, BarCodeHandle, 0, 'scanlines_valid')
dev_set_color ('green')
dev_display (ValidScanlines)
disp_message (WindowHandle, 'Valid scanlines detected', 'window', 72, 12, 'forest green', 'true')
endif
return ()