HALCON check_blister.hdev藥品膠囊檢測
示例程序源碼(加注釋)
-
顯示、讀入圖片、設置顯示字體等,之前的帖子已經介紹過了
dev_close_window ()
dev_update_off ()
read_image (ImageOrig, ‘blister/blister_reference’)
dev_open_window_fit_image (ImageOrig, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, ‘mono’, ‘true’, ‘false’)
dev_set_draw (‘margin’)
dev_set_line_width (3) -
第一步,我們創建一個圖案,以便在后續的水泡圖像中輕松切出腔室。
-
access_channel - 訪問多通道圖像中的指定的一個通道。這里選取Image1的第一個通道
access_channel (ImageOrig, Image1, 1) -
進行閾值分割,選取灰度值在90-255的區域
threshold (Image1, Region, 90, 255) -
使用shape_trans對區域Region處理,提取Region的外框,convex功能是外框
shape_trans (Region, Blister, ‘convex’) -
orientation_region計算區域的方向,這個算子是基于elliptic_axis 算子來的,elliptic_axis 是求取等效的橢圓,所以用算子orientation_region相當于把區域Blister轉化為一個等效橢圓,計算這個橢圓的長軸在圖像中的角度。
orientation_region (Blister, Phi) -
求取區域Blister的面積與中心坐標。
area_center (Blister, Area1, Row, Column) -
vector_angle_to_rigid - 根據初始坐標(前3個參數)與仿射變換后的坐標與角度(4-6,三個參數)角度生成一個旋轉與平移的仿射變換矩陣HomMat2D。這里初始坐標與結束坐標都沒有變化只是角度旋轉到了0度。
vector_angle_to_rigid (Row, Column, Phi, Row, Column, 0, HomMat2D) -
affine_trans_image - 對圖像進行任意的2D仿射變換。ImageOrig:要進行仿射變換的圖像;Image2:仿射變換之后的圖像;HomMat2D:2D仿射變換矩陣;constant:進行仿射變換的方式,這個代表使用均值濾波器來防止混疊效應的發生。false:仿射變換后的圖片超出現有圖片大小的區域不被剪切掉;若為true則相反。
affine_trans_image (ImageOrig, Image2, HomMat2D, ‘constant’, ‘false’) -
生成一個空的對象Chambers
gen_empty_obj (Chambers)for I := 0 to 4 by 1Row := 88 + I * 70for J := 0 to 2 by 1Column := 163 + J * 150* * 生成一個可旋轉的矩形;* 前兩個參數是區域中心坐標,第三個參數是矩形角度,后兩個參數是矩形的寬高。gen_rectangle2 (Rectangle, Row, Column, 0, 64, 30)* * concat_obj - 把兩個對象融合在一起。* 注意,這個和union不一樣,union是把兩個對象整合成一個對象,整合后對象的元素個數為1;* 而使用concat_obj 是把幾個對象聯合成一個對象,這個對象中的元素個數之和不變。concat_obj (Chambers, Rectangle, Chambers)endforendfor
-
使用變換矩陣HomMat2D對Blister區域使用nearest_neighbor方法進行仿射變換。
affine_trans_region (Blister, Blister, HomMat2D, ‘nearest_neighbor’) -
求取區域Blister與區域Chambers的差集
difference (Blister, Chambers, Pattern) -
將區域Chambers(有多個元素)聯合成一個區域(一個元素)
union1 (Chambers, ChambersUnion) -
求取區域Blister的角度
orientation_region (Blister, PhiRef) -
將角度PhiRef加180度
PhiRef := rad(180) + PhiRef -
求取區域Blister的面積與中心坐標
area_center (Blister, Area2, RowRef, ColumnRef) -
循環檢測每一張圖片
-
定義變量Count 賦值6
Count := 6 -
for循環
for Index := 1 to Count by 1-
讀入圖片
read_image (Image, ‘blister/blister_’ + Index$‘02’) -
對圖片Image進行閾值分割,提取像素灰度值在90-255的區域
threshold (Image, Region, 90, 255) -
分割連通域
connection (Region, ConnectedRegions) -
使用select_shape 對區域ConnectedRegions進行篩選,篩選出面積值介于5000-999999的區域
select_shape (ConnectedRegions, SelectedRegions, ‘area’, ‘and’, 5000, 9999999) -
求取區域SelectedRegions的外形
shape_trans (SelectedRegions, RegionTrans, ‘convex’) -
求取區域RegionTrans的角度
orientation_region (RegionTrans, Phi) -
求取區域RegionTrans的面積與中心坐標
area_center (RegionTrans, Area3, Row, Column) -
生成仿射變換矩陣HomMat2D
vector_angle_to_rigid (Row, Column, Phi, RowRef, ColumnRef, PhiRef, HomMat2D) -
使用HomMat2D矩陣對Image進行仿射變換
affine_trans_image (Image, ImageAffinTrans, HomMat2D, ‘constant’, ‘false’) -
使用區域剪切圖片,縮小圖像處理定義域
reduce_domain (ImageAffinTrans, ChambersUnion, ImageReduced) -
將圖片ImageReduced分成R/G/B三通道圖像
decompose3 (ImageReduced, ImageR, ImageG, ImageB) -
var_threshold - 通過局部均值和標準差分析對圖像進行閾值處理。
var_threshold (ImageB, Region, 7, 7, 0.2, 2, ‘dark’) -
分割連通域
connection (Region, ConnectedRegions0) -
使用矩形對區域進行閉運算
closing_rectangle1 (ConnectedRegions0, ConnectedRegions, 3, 3) -
填充孔洞
fill_up (ConnectedRegions, RegionFillUp) -
進行面積篩選
select_shape (RegionFillUp, SelectedRegions, ‘area’, ‘and’, 1000, 99999) -
使用圓形元素對區域進行開運算
opening_circle (SelectedRegions, RegionOpening, 4.5) -
分割連通域
connection (RegionOpening, ConnectedRegions) -
進行面積篩選
select_shape (ConnectedRegions, SelectedRegions, ‘area’, ‘and’, 1000, 99999) -
求取區域輪廓
shape_trans (SelectedRegions, Pills, ‘convex’) -
對區域Chambers進行計數
count_obj (Chambers, Number) -
生成一個空的對象
gen_empty_obj (WrongPill) -
生成一個空的對象
gen_empty_obj (MissingPill) -
for循環
for I := 1 to Number by 1- 在對象數組中選取指定對象,之前例子已經講過了
select_obj (Chambers, Chamber, I) - 求交集
intersection (Chamber, Pills, Pill) - 求取區域面積與中心坐標值
area_center (Pill, Area, Row1, Column1)
if (Area > 0)
* 求取最大最小的灰度值,之前例子已經講過了
min_max_gray (Pill, ImageB, 0, Min, Max, Range)
if (Area < 3800 or Min < 60)
* 聯合對象,上邊有介紹
concat_obj (WrongPill, Pill, WrongPill)
endif
else
* 聯合對象,上邊有介紹
concat_obj (MissingPill, Chamber, MissingPill)
endif
endfor - 在對象數組中選取指定對象,之前例子已經講過了
-
下面的就是顯示了
dev_clear_window ()
dev_display (ImageAffinTrans)
dev_set_color (‘forest green’)
count_obj (Pills, NumberP)
count_obj (WrongPill, NumberWP)
count_obj (MissingPill, NumberMP)
dev_display (Pills)
if (NumberMP > 0 or NumberWP > 0)
disp_message (WindowHandle, ‘Not OK’, ‘window’, 10, 10 + 600, ‘red’, ‘true’)
else
disp_message (WindowHandle, ‘OK’, ‘window’, 10, 10 + 600, ‘forest green’, ‘true’)
endif
disp_message (WindowHandle, '# correct pills: ’ + (NumberP - NumberWP), ‘window’, 10, 10, ‘black’, ‘true’)
disp_message (WindowHandle, '# wrong pills : ’ + NumberWP, ‘window’, 10 + 25, 10, ‘black’, ‘true’)
if (NumberWP > 0)
disp_message (WindowHandle, NumberWP, ‘window’, 10 + 25, 10 + 180, ‘red’, ‘true’)
endif
disp_message (WindowHandle, '# missing pills: ’ + NumberMP, ‘window’, 10 + 50, 10, ‘black’, ‘true’)
if (NumberMP > 0)
disp_message (WindowHandle, NumberMP, ‘window’, 10 + 50, 10 + 180, ‘red’, ‘true’)
endif
dev_set_color (‘red’)
dev_display (WrongPill)
dev_display (MissingPill)
if (Index < Count)
disp_continue_message (WindowHandle, ‘black’, ‘true’)
endif
stop ()
endfor
-
處理思路
在這個例子是藥品行業膠囊的檢測,是比較經典的例子,我們下一篇文章介紹另一個膠囊檢測例子。這個膠囊檢測首先用到了仿射變換,把每個膠囊的單元提取出來,然后使用最簡單的blob分析對缺陷進行提取。
后記
大家有什么問題可以向我提問哈,我看到了第一時間回復,希望在學習的路上多多結交良師益友。