HALCON示例程序check_fish_stick_dimension.hdev基于形態學的像素級精度尺寸測量
示例程序源碼(加注釋)
-
關閉實時顯示更新
dev_update_off () -
關閉窗口
dev_close_window () -
讀入圖片
read_image (Image, ‘food/fish_sticks_raw_01’) -
根據給定長寬比開辟窗口并顯示圖像
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) -
設置字體顯示格式
set_display_font (WindowHandle, 16, ‘mono’, ‘true’, ‘false’) -
區域以邊緣形式進行顯示
dev_set_draw (‘margin’) -
獲取系統關于“空白區域儲存的設置”并進行設置,上一篇介紹過了
get_system (‘store_empty_region’, StoreEmptyRegion)
set_system (‘store_empty_region’, ‘true’) -
變量的聲明與賦值
cm_per_pix := 0.0373
TargetLength := 9.0
ToleranceHigh := 0.8
ToleranceLow := 0.2 -
定義圖片數量
NumImages := 10 -
循環檢測
for I := 1 to NumImages by 1-
讀入圖片
read_image (Image, ‘food/fish_sticks_raw_’ + I$’.2’) -
分割生魚棒,將測量區域提取出來
-
閾值分割選取灰度值在50-255的像素
threshold (Image, Region, 50, 255) -
分割連通域
connection (Region, ConnectedRegions) -
填充孔洞,使選取的生魚棒完整
fill_up (ConnectedRegions, RegionFillUp) -
篩選面積在1000-99999的區域,消除雜點干擾
select_shape (RegionFillUp, SelectedRegions, ‘area’, ‘and’, 1000, 99999) -
選擇不與圖像邊框相交的區域,不檢測與圖像邊緣相交的生魚棒,因為它不完整
-
使用形態學運算來計算區域的邊界,這里就是將圖片邊界提取出來
boundary (Image, RegionBorder, ‘inner’) -
求圖像邊界與提取出生魚棒區域的交集,如果有交集那么證明有生魚棒位于圖像邊界,不進行檢測。
intersection (SelectedRegions, RegionBorder, RegionIntersection) -
求解上一步求出的交集的面積與坐標
area_center (RegionIntersection, Area, Row1, Column1) -
find(Area,0)這個算子意思是在Area數組里邊尋找0這個元素,并且返回索引號;這里又在后邊加
-
了個 1,交集區域為空所以 Area:=[0,0,0,0],find(Area,0):=[0,1,2,3],
-
ValidRegionIndices := [1,2,3,4];如果find在Area數組內沒有找到0,則返回-1
ValidRegionIndices := find(Area,0) + 1 -
如果ValidRegionIndices第一個元素不等0;ValidRegionIndices := []為空
if (ValidRegionIndices[0] == 0)
ValidRegionIndices := []
endif -
halcon自定義函數,目的在數組(第一個參數)尋找大于數值(第二個參數)的值,并返回索引號。
select_tuple_larger (Area, 0.0, RegionAtBorderIndices)
select_tuple_larger函數內部代碼:
** sgn()返回數值的符號,(-1,0,1) **這里就是數組里邊的值與輸入值相減,根據符號判斷1為正,之后用find返回數組數值為1的索引號
tuple_find (sgn(Tuple - Value), 1, Indices)
if (Indices[0] == -1)
Indices := []
endif
return ()RegionAtBorderIndices := RegionAtBorderIndices + 1
-
select_obj 在元組中選取指定對象
-
選取要正常測量的區域
select_obj (SelectedRegions, ValidSticks, ValidRegionIndices) -
選取位于邊界的區域
select_obj (SelectedRegions, StickAtBorder, RegionAtBorderIndices) -
測量生魚棒的尺寸
-
求取生魚棒的可旋轉最小外接矩形
smallest_rectangle2 (ValidSticks, Row, Column, Phi, Length1, Length2) -
求取生魚棒的實際長度,用像素個數乘以像素尺寸
FishLength1 := Length1 * 2 * cm_per_pix -
選取尺寸大于最小要求尺寸的生魚棒
select_tuple_larger (FishLength1, TargetLength - ToleranceLow, IndicesGood) -
選取尺寸大于最大要求尺寸的生魚棒
select_tuple_larger (FishLength1, TargetLength + ToleranceHigh, IndicesBad1) -
tuple_remove從元組中刪除元素,將尺寸大于最大要求尺寸的生魚棒剔除
tuple_remove (IndicesGood, IndicesBad1, IndicesGood) -
選取小于最小要求尺寸的生魚棒
select_tuple_larger (-FishLength1, -(TargetLength - ToleranceLow), IndicesBad2) -
將大于最大要求尺寸與小于最小要求尺寸的壞的生魚棒的索引號合并到一個壞的生魚棒的數組
IndicesBad := [IndicesBad1,IndicesBad2] -
subset()選擇元組元組的一個或多個單個元素,相當于將好壞的坐標選取出來
RowGood := subset(Row,IndicesGood)
ColumnGood := subset(Column,IndicesGood)
RowBad := subset(Row,IndicesBad)
ColumnBad := subset(Column,IndicesBad)
FishLength1Good := subset(FishLength1,IndicesGood)
FishLength1Bad := subset(FishLength1,IndicesBad) -
繪制外接矩形框
if (|IndicesGood| > 0)
gen_rectangle2 (GoodSticks, RowGood, ColumnGood, subset(Phi,IndicesGood), subset(Length1,IndicesGood), subset(Length2,IndicesGood))
else
gen_empty_obj (GoodSticks)
endif
if (|IndicesBad| > 0)
gen_rectangle2 (BadSticks, RowBad, ColumnBad, subset(Phi,IndicesBad), subset(Length1,IndicesBad), subset(Length2,IndicesBad))
else
gen_empty_obj (BadSticks)
endif -
顯示結果
dev_display (Image)
dev_set_color (‘white’)
dev_set_line_width (1)
dev_display (ValidSticks)
dev_set_line_width (3)
dev_set_color (‘yellow’)
dev_display (StickAtBorder)
dev_set_color (‘green’)
dev_display (GoodSticks)
dev_set_color (‘red’)
dev_display (BadSticks) -
′.1f′這個是代表浮點數顯示小數點后一位String:=′Targetlength:′+TargetLength'.1f'這個是代表浮點數顯示小數點后一位 String := 'Target length: ' + TargetLength′.1f′這個是代表浮點數顯示小數點后一位String:=′Targetlength:′+TargetLength‘.1f’ + ’ cm’
String[1] := ‘Tolerance: -’ + ToleranceLow′.1f′+′/+′+ToleranceHigh'.1f' + '/+' + ToleranceHigh′.1f′+′/+′+ToleranceHigh’.1f’
disp_message (WindowHandle, String, ‘window’, 12, 12, ‘black’, ‘true’)
for J := 0 to |IndicesGood| - 1 by 1
disp_message (WindowHandle, ‘OK’, ‘image’, 80, ColumnGood[J] - 10, ‘green’, ‘false’)
disp_message (WindowHandle, FishLength1Good[J]′.1f′+′cm′,′image′,RowGood[J],ColumnGood[J]?28,′white′,′false′)endforforJ:=0to∣IndicesBad∣?1by1dispmessage(WindowHandle,′NotOK′,′image′,80,ColumnBad[J]?30,′red′,′false′)dispmessage(WindowHandle,FishLength1Bad[J]'.1f' + 'cm', 'image', RowGood[J], ColumnGood[J] - 28, 'white', 'false') endfor for J := 0 to |IndicesBad| - 1 by 1 disp_message (WindowHandle, 'Not OK', 'image', 80, ColumnBad[J] - 30, 'red', 'false') disp_message (WindowHandle, FishLength1Bad[J]′.1f′+′cm′,′image′,RowGood[J],ColumnGood[J]?28,′white′,′false′)endforforJ:=0to∣IndicesBad∣?1by1dispm?essage(WindowHandle,′NotOK′,′image′,80,ColumnBad[J]?30,′red′,′false′)dispm?essage(WindowHandle,FishLength1Bad[J]’.1f’ + ‘cm’, ‘image’, RowBad[J], ColumnBad[J] - 28, ‘white’, ‘false’)
endfor
if (I != NumImages)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
stop ()
endif
endfor -
-
恢復系統設置
set_system (‘store_empty_region’, StoreEmptyRegion)
處理思路
普通的形態學進行區域的分割與測量,這個例子給我最大的收獲就是如何找到與圖像邊界重疊的區域,還有關于halcon下數組相關的操作,比如sgn、find、select_obj、subset等。
后記
大家有什么問題可以向我提問哈,我看到了第一時間回復,希望在學習的路上多多結交良師益友。