Halcon中線條提取的算子主要有:
lines_color(Image : Lines : Sigma, Low, High, ExtractWidth, CompleteJunctions : )
lines_facet(Image : Lines : MaskSize, Low, High, LightDark : )
lines_gauss(Image : Lines : Sigma, Low, High, LightDark, ExtractWidth, LineModel, CompleteJunctions : )
其中lines_facet、 lines_gauss又可以歸為同一類(從幫助文檔的算子簽名Signature可知這一點)。
一、線條提取和邊緣提取的區別
上面三個線條提取的算子,輸出的是一堆XLD;而 edges_sub_pix 這種邊緣提取算子,得到的也是一堆XLD。那么它們有什么區別呢?
舉個例子說明:

1 read_image (Image, 'angio-part') 2 count_channels (Image, Channels) 3 if (Channels == 3 or Channels == 4) 4 rgb1_to_gray (Image, Image) 5 endif 6
7 lines_gauss (Image, Lines, 2.3, 0.0, 0.7, 'dark', 'true', 'parabolic', 'true') 8 edges_sub_pix (Image, Edges, 'canny', 1, 5, 10) 9 dev_set_color ('green') 10 dev_display (Image) 11 dev_display (Lines)
lines_gauss和edges_sub_pix 輸出的XLD的區別對比如下:

相信大家已經看出了兩者的區別了。
圖像的“邊緣”指的是:圖像中灰度有明顯跳變的地方。如果在圖中畫一條“有一定寬度的線”,那么線的兩側應該都可以提取到邊緣。
而線條提取的算子(例如lines_gauss)提取的是這條“有一定寬度的線”的“骨架線”,它一般只有一根。
為什么我想寫一篇文章單獨講“線條提取”呢?主要因為跟我目前工作遇到的困難有關。
公司目前在用傳統算法 + 深度學習做復雜缺陷檢測。如果用Halcon做缺陷檢測的話,用到的無非是形態學分析、頻域處理、特征篩選等等,但是對於不太明顯或者難以定位分割的缺陷,Halcon就束手無策了。但是深度學習在這方面有獨特的優勢,它可以通過標注大量的缺陷形態,不斷訓練學習,從而獲得對復雜缺陷的識別定位能力。
但是對於“較淺且大批量出現的划痕”這種缺陷類型,深度學習也束手無策,因為它很難去逐個標注這些缺陷——一方面標注工作量太大,一方面很難准確地標注。
划痕,其實就是一種線條,用Halcon提供的線條提取算子,可以很輕松找出這些划痕(或線條)。
二、lines_color
算子描述為:檢測有色的線條及其寬度。
lines_color(Image : Lines : Sigma, Low, High, ExtractWidth, CompleteJunctions : )
該算子從輸入圖像Image中提取彩色線條,並將提取的線條以亞像素XLD輪廓的形式返回Lines。
Sigma——要應用的高斯平滑量。
Low——磁滯閾值操作的下限閾值。
High——磁滯閾值操作的上限閾值。
ExtractWidth——應該提取線寬嗎?(一般選擇‘true’)
CompleteJunctions——是否應該在無法提取的地方添加連接點?
注意:
如果使用較大的平滑量(Sigma),應相應地為“High”和“Low”選擇較小的值。
一般來說,特別是在需要提取線條寬度的時候,參數Sigma的選擇應該滿足Sigma >= w/1.732(w代表圖像中線條的寬度(線條直徑的一半)),最小允許值是Sigma >= w/2.5。例如,對於一個寬度為4個像素(直徑為8個像素)的線條來說,Sigma >= 2.3是合適的參數。(4/1.732 = 2.3)
下面研究一下CompleteJunctions參數的意思。它可取的值有true或者false。該參數的意思為:是否應該在無法提取的地方添加連接點?
那它到底有什么作用呢?舉例說明:

1 read_image (Image, 'cable1') 2 lines_color (Image, Lines1, 3.5, 0, 12, 'true', 'false') 3 lines_color (Image, Lines2, 3.5, 0, 12, 'true', 'true') 4
5 dev_set_color ('green') 6 dev_clear_window () 7 dev_display (Lines1) 8 dev_clear_window () 9 dev_display (Lines2)

意思很明顯了,當CompleteJunctions = 'true'時,會在無法提取的地方添加連接點,這樣某些XLD可能會連起來。參考官方示例程序:lines_color.hdev。
三、lines_facet
算子描述為:使用小平面模型檢測線條。
lines_facet(Image : Lines : MaskSize, Low, High, LightDark : )
下面的觀點提煉自幫助文檔:
① 參數LightDark確定是提取亮線還是暗線。
② MaskSize的值越大,圖像的平滑度就越大,但可能會導致線條的局部化程度更差;MaskSize的值越小,提取的線條越短,碎片越多,但這可能會導致相當長的執行時間。
③ 關於取值,當Sigma=1.5時,此時大致對應於MaskSize 的值為5。
但是,這個算子我們一般不用。因為如何給MaskSize、Low、High取合適的值確實是一門技術活,不好掌握,更重要的lines_gauss算子完全可以替代它,並且更易掌握。OK,忘記lines_facet吧。
四、lines_gauss
算子描述為:檢測線及其寬度。
lines_gauss(Image : Lines : Sigma, Low, High, LightDark, ExtractWidth, LineModel, CompleteJunctions : )
這里多了一個參數LineModel(其他參數前面都說過)。
LineModel:提取線條的模式,有'none', 'bar-shaped', 'parabolic', 'gaussian' 四種。含義如下:

對大多數應用來說,LineModel的'bar-shaped'參數是正確的選擇,'parabolic'參數常用來提取邊緣比較銳利的線條(比如背光照明的圖像中的線條),'gaussian'則在線條邊緣不那么銳利的時候使用。參數LineModel僅在參數ExtractWidth被設置為'true'時才有意義。
上圖中,可以看出'parabolic'圖示中,箭頭指向的過渡處過渡陡峭(適合提取銳利的線條)。而'gaussian'圖示中,箭頭指向的過渡處過渡平滑(適合提取邊緣平滑的線條)。
其實lines_gauss算子的參數是最多的,因此參數如何正確取值一點都不簡單。但是很明顯,官方偏愛lines_gauss這個算子,它們開發了calculate_lines_gauss_parameters算子。
calculate_lines_gauss_parameters( : : MaxLineWidth, Contrast : Sigma, Low, High)
算子描述為:根據要提取的線條的最大寬度和對比度計算lines_gauss的參數Sigma、Low和High。
MaxLineWidth定義要使用lines_gauss提取的線條的最大寬度。
Contrast參數應設置為要提取的典型線條的灰度值對比度。在任何情況下都將提取具有較高對比度的所有線條。
Contrast參數可以設為具有兩個值的元組(例如[60, 10]),第二個值定義為要提取的線的最小對比度。
第二個值不能大於第一個值。如果只給出一個值,則最小對比度默認為對比度/3.0。
最小對比度的值越小,線條越長,線條延伸到對比度低的區域;值越高,線條越短,但線條越突出。
還是以前面的圖為例:
1 read_image (Image, 'angio-part') 2 count_channels (Image, Channels) 3 if (Channels == 3 or Channels == 4) 4 rgb1_to_gray (Image, Image) 5 endif 6
7 calculate_lines_gauss_parameters (8, [10,4], Sigma, Low, High) 8 lines_gauss (Image, Lines, Sigma, Low, High, 'dark', 'true', 'parabolic', 'true') 9
10 dev_set_color ('green') 11 dev_display (Image) 12 dev_display (Lines)

由前文可知,對於線條提取,我們只需要掌握lines_color和lines_gauss這兩個算子即可。
參考資料:
【Halcon】2D測量之三
lines_gauss用法解析
