HALCON在使用默认参数检测一维码时有时会出现只检测到部分,或者没检测到的情况,我们除了调整参数,还可以通过减少检测区域来解决,根据二维码的特征筛选出二维码区域
dev_get_window (WindowHandle)
list_files ('F:/一维码/一维码', ['files','follow_links','recursive'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
median_image (Image, Image, 'circle', 2, 'mirrored')
laplace_of_gauss(Image, ImageLaplace, 2)//提取边缘轮廓
threshold(ImageLaplace, Region3, 2, 111)//阈值分割
skeleton(Region3, Skeleton3)//计算区域骨架
connection (Skeleton3, ConnectedRegions)//连通性分析
select_shape (ConnectedRegions, SelectedRegions1, 'area', 'and', 60, 1500)//通过面积筛选
select_shape_std (SelectedRegions1, SelectedRegions, 'rectangle2', 30)//通过矩形度筛选
union1 (SelectedRegions, RegionUnion)//合并
gen_contours_skeleton_xld (RegionUnion, Contours1, 1, 'filter')//骨架转化为xld轮廓
*通过轮廓长度再次筛选
select_contours_xld (Contours1, SelectedContours, 'contour_length', 30, 400, -0.5, 0.5)
*根据XLD轮廓拟合直线
fit_line_contour_xld (SelectedContours, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist1)
*将拟合的直线显示为区域
gen_region_line (RegionLines1, RowBegin, ColBegin, RowEnd, ColEnd)
*在-180~180°里每30°查找一次条码
for i:=180 to -170 by -30
*筛选角度差30°的拟合线//根据角度筛选区域
select_shape (RegionLines1, SelectedRegions2, 'orientation', 'and', rad(i-30), rad(i))
*获取筛选到的区域
count_obj (SelectedRegions2, Number)
*少于12条说明不是条码//区域数量大于12
if(Number>=12)
*将所有拟合线联合为一个区域
union1 (SelectedRegions2, RegionUnion1)
*求坐标和角度
area_center (RegionUnion1, Area1, Row, Column)
orientation_region (RegionUnion1, Phi)
*如果角度不在-90°~90°之间,说明求角度的凸性反向错了,因为我们都要转至0°的反向
if(Phi>rad(90))
Phi:=Phi-rad(180)
endif
if(Phi<-rad(90))
Phi:=rad(180)+Phi
endif
*旋转句柄
vector_angle_to_rigid (Row, Column, Phi, Row, Column,rad(0), HomMat2D)
*旋转区域和图像,即将条码转至水平位置(与y轴平行)
affine_trans_region (RegionUnion1, RegionAffineTrans1, HomMat2D, 'nearest_neighbor')
affine_trans_image (Image, ImageAffineTrans1, HomMat2D, 'constant', 'false')
*宽度200高度2的结构元素用于膨胀水平方向,连接条码为一个区域
closing_rectangle1 (RegionAffineTrans1, RegionClosing, 200, 2)
*有些线段与条码的角度相同,此时通过面积过滤
connection (RegionClosing, ConnectedRegions1)//连通性分析
*选择面积最大的区域
select_shape_std (ConnectedRegions1, SelectedRegions4, 'max_area', 70)
*将区域转换成矩形
shape_trans (SelectedRegions4, RegionTrans, 'rectangle2')
*为了保证提取的区域是条码区域,可以通过一些条件进一步判断是否条码区域
*通过颜色特征(条码区域黑白相间,面积应该差不多)
reduce_domain (ImageAffineTrans1, RegionTrans, ImageReduced1)
*白色区域
threshold (ImageReduced1, Regions1, 89, 255)
area_center (Regions1, Area, Row1, Column1)
*黑色区域
threshold (ImageReduced1, Regions2, 0, 89)
area_center (Regions2, Area2, Row2, Column2)
if(Area>Area2*2 or Area2>Area*2 )//如果白色面积大与黑色一倍或白色比黑色大一倍
continue//停止当前循环,进行下一次循环
else
break//退出循环
endif
break//退出循环
endif
endfor
*膨胀,防止条码区域太小
dilation_circle (RegionTrans, RegionDilation, 50)
*减少定义域
reduce_domain (ImageAffineTrans1, RegionDilation, ImageReduced)
create_bar_code_model ([], [], BarCodeHandle)//创建一维码模型,输入模型的参数,输出一个模型的句柄
*set_bar_code_param (BarCodeHandle, 'timeout', 1020)//设置延迟
dev_display (Image)
dev_display (ImageAffineTrans1)
find_bar_code (ImageReduced, SymbolRegions, BarCodeHandle, 'auto', DecodedDataStrings)//检测一维码
*Image:查找的图像;BarCodeHandle:一维码模型句柄;CodeType:一维码的类型;DecodedDataStrings:解码的一维码数据字符串
count_obj (SymbolRegions, Number)
if (Number<1)//判断是否检测到
disp_message (WindowHandle, '未检测到条码', 'ImageAffineTrans1', 12, 12, 'black', 'true')
stop ()
endif
area_center (SymbolRegions, Area, Row, Column)//获取区域信息
disp_message (WindowHandle, DecodedDataStrings, 'ImageAffineTrans1', Row, Column-200, 'black', 'false')//显示结果
clear_bar_code_model (BarCodeHandle)//清除模板
stop ()
endfor