引言
條碼識別的應用大多數在物流行業中(需要識別的條碼一般在快遞包裹中),對於一維碼的識別,halcon有自帶條碼識別算子create_bar_code_model和find_bar_code 。而快遞標簽處有很多的文字,符號和邊框,增大了定位的難度。,因此有時也有檢測不到條碼的情況。針對這一現象,本篇就來深度分析一下如何更好的去識別一維碼。
一,相關算子分析
-
create_bar_code_model(創建一維碼模型)
create_bar_code_model ([], [], BarCodeHandle) 參數一//輸入 需要調整的參數名稱(為[]表示暫時不設置) 參數二//需要調整的該參數的值。 參數三// 返回的條碼模板句柄
- set_bar_code_param(對模型設置參數)
set_bar_code_param( BarCodeHandle, GenParamNames, GenParamValues ) BarCodeHandle(in)//模型句柄 GenParamNames(in)//參數名稱 GenParamValues (in)//參數值
-
find_bar_code (識別一維碼)
find_bar_code(Image ,SymbolRegions ,BarCodeHandle, CodeType , DecodedDataStrings) 參數列表: Image //輸入圖像 SymbolRegions//檢測到的條形碼區域(輸出) BarCodeHandle// 條形碼句柄 CodeType// 條形碼類型 DecodedDataStrings//識別結果(輸出)
二,提高解碼能力的其他措施
(1)圖像預處理(增強條碼)
- 對比度太低:scale_image(或使用外部程序scale_image_range),增強圖像的對比度。
- 圖像模糊:emphasize銳化圖像,使條碼看起來更清晰。
- 深色背景上讀取淺色條碼:invert_image反轉圖像。
(2)如果整張圖信息太多,則可以先把條碼區域挖出來,使用reduce_domain和crop_domain算子,這樣不僅可以降低解碼難度,還可以減少解碼時間。也可使用decode_bar_code_rectangle2在指定的矩形區域內解碼。
(3)當條碼很密或者很小的時候,可以嘗試用zoom_image_factor放大了條碼圖像。
(4)find_bar_code中將“CodeType”設置為“auto”可以讀取多種類型的條碼,但是會增加運行時間,且可能會降低解碼的可靠性。最好只掃描預知的條形碼類型。
三,如何在圖像提取條碼區域
以快遞上的一維碼為例,由於快遞標簽處有很多的文字,符號和邊框,增大了定位的難度。(如下圖)而且有很多噪聲的影響。
halcon實現:
1,讀入圖像,提取輪廓
有兩種方法:
- 基於邊緣提取
- blob分析
read_image (Image, 'C:/Users/86175/Desktop/4.png') get_image_size (Image, Width, Height) dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle) dev_display (Image) rgb1_to_gray (Image, GrayImage) *第一種邊緣提取初步提取輪廓 laplace_of_gauss(GrayImage, ImageLaplace, 2)//拉布拉斯算子 threshold(ImageLaplace, Region3, 5, 127) skeleton(Region3, Skeleton3) connection (Skeleton3, ConnectedRegions2) select_shape (ConnectedRegions2, SelectedRegions, ['area','width','height'], 'and', [0,0,0], [220,80,200]) *第二種Blob分析法初步提取條碼 threshold (GrayImage, Regions, 7, 107) connection (Regions, ConnectedRegions)
二者提取效果差不多,但是考慮到Blob分析法可能對相機像素有較大的要求,否則二值化后可能提取不出條碼線,個人覺得用邊緣提取的方式較穩定。
2,篩選條碼區域
*通過面積和矩形度篩選 select_shape (ConnectedRegions, SelectedRegions1, 'area', 'and', 60, 1500) select_shape_std (SelectedRegions1, SelectedRegions, 'rectangle2', 60) *提取輪廓 union1 (SelectedRegions, RegionUnion) skeleton (RegionUnion, Skeleton4) gen_contours_skeleton_xld (Skeleton4, Contours1, 1, 'filter') *通過輪廓長度過濾小噪聲 select_contours_xld (Contours1, SelectedContours, 'contour_length', 30, 200, -0.5, 0.5)
3,擬合直線,進一步篩選
*因為條碼都是直線,可以通過角度相同的直線分割條碼 *擬合直線 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) *在0~-180°里每-30°查找一次條碼 for i:=-1 to -150 by -30 select_shape (RegionLines1, SelectedRegions3, 'phi', 'and', rad(i-30), rad(i)) count_obj (SelectedRegions3, Number) if(Number>12) union1 (SelectedRegions3, RegionUnion1) area_center (RegionUnion1, Area1, Row, Column) orientation_region (RegionUnion1, Phi) 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) affine_trans_region (RegionUnion1, RegionAffineTrans1, HomMat2D, 'nearest_neighbor') affine_trans_image (GrayImage, ImageAffineTrans, HomMat2D, 'constant', 'false') closing_rectangle1 (RegionAffineTrans1, RegionClosing, 80, 2) connection (RegionClosing, ConnectedRegions1) select_shape (ConnectedRegions1, SelectedRegions4, 'area', 'and', 2954.26, 50000) shape_trans (SelectedRegions4, RegionTrans, 'rectangle2') region_features (RegionTrans, 'width', w) region_features (RegionTrans, 'height', h) if(w/h<2.5 or w/h>10) continue endif reduce_domain (ImageAffineTrans, RegionTrans, ImageReduced1) threshold (ImageReduced1, Regions1, 160, 254) area_center (Regions1, Area, Row1, Column1) threshold (ImageReduced1, Regions2, 0, 120) area_center (Regions2, Area2, Row2, Column2) if(Area>Area2) if(Area/Area2>2) continue endif endif if(Area2>Area) if(Area2/Area>2) continue endif endif dilation_circle (RegionTrans, RegionDilation, 6) reduce_domain (ImageAffineTrans, RegionDilation, ImageReduced) endif endfor