Halcon算子学习:图像阈值分割-threshold、binary_threshold、dyn_threshold算子
Halcon算子學習:圖像閾值分割算子
- 前言
- 1.threshold-全局固定閾值分割
- 2.Binary Threshold-自動全局閾值分割
- 3.dyn_threshold-局部動態閾值分割
- 小結:
- 4.var_threshold算子-均值和標準偏差局部閾值分割
- 5.dual_threshold-雙重閾值分割(有符號圖像的閾值算子)
- 6.auto_threshold-自動全局閾值分割
- 7.fast_threshold-快速全局閾值分割
- 8.watersheds-分水嶺算法分割
前言
圖像二值化是圖像分析與處理中最常見最重要的處理手段,二值處理方法也非常多。越精準的方法計算量也越大。參考博客:
- 圖像處理之常見二值化方法匯總
- Halcon閾值化算子dual_threshold和var_threshold的理解
1.threshold-全局固定閾值分割
threshold(Image : Region : MinGray, MaxGray : )
——使用全局固定閾值分割圖像
閾值從輸入圖像中選取灰度值g滿足以下條件的像素點
滿足條件的圖像的所有點作為一個區域返回。如果傳遞多個灰度值間隔(MinGray和MaxGray的元組),則每個間隔返回一個單獨的區域。對于向量場圖像,閾值不應用于灰度值,而是應用于向量的長度。
應用一:利用灰度直方圖確定閾值進行圖像分割。一般是物體與背景之間存在一個明顯的灰度差,直方圖會存在兩個波峰一個是目標一個是背景,那么閾值就是物體與背景之間的最小值。
read_image (Image, 'clip') *計算直方圖 gray_histo (Image, Image, AbsoluteHisto, RelativeHisto) *將直方圖轉換為區域(包含直方圖的區域;輸入的直方圖;直方圖中心的行/列坐標;直方圖的比例因子) gen_region_histo (Region, AbsoluteHisto, 255, 255, 1) *利用直方圖獲取閾值 histo_to_thresh (AbsoluteHisto,10, MinThresh, MaxThresh) *期望閾值 TarGetGray:=23 for Index := |MinThresh|-1 to 0 by -1if(MinThresh[Index]<=TarGetGray)MinThresh:= MinThresh[Index]breakendifendforfor Index1 := 0 to |MaxThresh|-1 by 1if (MaxThresh[Index1]>=TarGetGray)MaxThresh:=MaxThresh[Index1]breakendifendfor *全局閾值分割 threshold (Image, Region1, MinThresh, MaxThresh)
2.Binary Threshold-自動全局閾值分割
參考: 閾值分割算子之OSTU算法(binary_threshold)
binary_threshold(Image : Region : Method, LightDark : UsedThreshold)
——自動全局閾值分割(自動確定的全局閾值分割單通道圖像,并在區域中返回分割后的區域)
輸入:
- Image:需要進行閾值的圖像
- Region:處理后的區域
輸出:
- Method:分割方法(‘max_separability’:最大限度的可分性, ‘smooth_histo’:直方圖平滑)
- LightDark:提取的是黑色部分還是白色部分
- UsedThreshold:自動閾值使用的閾值值
例如,分割均勻照明的背景上有用的字符。binary_threshold還返回UsedThreshold中使用的閾值。
使用的閾值由方法中給出的方法確定。目前,該操作符提供了以下兩個方法:
’max_separability’:最大限度的可分性, ‘smooth_histo’:直方圖平滑。
這兩種方法只能用于具有雙峰直方圖的圖像。(如下圖)
smooth_histo方法提供的功能與操作符bin_threshold提供的功能相同。方法’max_separability’傾向于為UsedThreshold確定較小的值。此外,它對柱狀圖中的稀疏孤立峰不那么敏感,而且通常比‘smooth_histo’更快。
最大限度的可分性(max_separability):
通過選擇Method= ’ max_separability ',根據“灰度直方圖的閾值選擇方法”的灰度直方圖自動閾值調用。該算法首先計算圖像的直方圖,然后利用統計矩找到將像素分割為前景和背景的最優閾值,并最大化這兩個類之間的可分性。此方法僅適用于byte和uint2圖像。
如果LightDark = ‘light’,則選中所有灰度值大于或等于"T*"的像素。
如果LightDark = ‘dark’,則選中所有灰色值小于"T*"的像素。
直方圖平滑(smooth_histo):
通過選擇Method = 'smooth_histo ’ binary_threshold可以通過以下方式確定閾值:首先確定灰度值的相對直方圖。然后,從直方圖提取相關的最小值,作為閾值操作的參數。為了減少最小值,直方圖被平滑處理為一個高斯函數,就像在auto_threshold中一樣。在平滑直方圖中,掩模尺寸增大,直到最小值。然后,閾值設置為這個最小值的位置。
如果LightDark = ‘light’,則選中所有灰度值大于或等于"T*"的像素。
如果LightDark = ‘dark’,則選中所有灰色值小于"T*"的像素。
3.dyn_threshold-局部動態閾值分割
dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : )
——局部動態閾值分割 Dynamic Threshold
- ThresholdImage:是我們用來作為灰度值參考的另外一幅圖像,在實際使用過程中通常都是對原圖像OrigImage進行一次平滑處理,然后用平滑處理之后得到的圖像作為參考圖像。
- LightDark:是問我們提取亮?暗?還是相似的區域?(當然,這是相對于ThresholdImage)
- Offset:其實是在設定一個比較的區間范圍,因為在圖像處理這個主觀性本來就比較強的領域中“絕對”這個科學名次實在有點太過分,所以什么事情,只要在一個合理的范圍內,我們都是可以接受的,而不是死死抓住一個點不放,最后也得不到想要的結果。
dyn_threshold 這個算子就是根據一套灰度值比較規則來選擇原圖像中那些灰度值符合這個公式的像素點。
令
g_{o} = g_{OrigImage}; 代表原圖中的像素點的灰度值
g_{t} = g_{ThresholdImage};代表參考圖中的像素點的灰度值
我們的做法是把參考圖像的灰度值加上(減去)一個Offset,然后去和原圖的像素點逐像素對應地進行比較。
下面看Halcon中給出的這些公式:
-
當參數 LightDark = ‘light’ 時,
既然選擇light,那就代表提取相對參考圖來說亮一些的地方,那么自然要選擇那些灰度值比 gt + Offset 要大的像素點。
-
當參數 LightDark = ‘dark’ 時:
如果要提取的是比參考圖要暗一些的區域,那么自然要選擇比g_t的灰度值要小的那些像素點,但是這樣直接比較的話提取的小區域太多了,并沒有很好地提取出相對參考圖來說很明顯有差別的那部分,所以我們才給定Offset這個參數用來修正。這樣給參考圖的灰度值一減掉Offset,提取出來的和參考的之間的差距就會很明顯。
-
當參數 LightDark = ‘equal’ 時,
選擇equal的意思是選擇那些和參考圖的差不多的,只要在這個合理的范圍內的都算。
-
最后, 當 LightDark = 'not_equal’時
反正只要不是差不多的就不選,亮的暗的無所謂。
通常,閾值圖像是原始圖像的平滑版本(例如,通過應用mean_image、binomial_filter、gauss_filter等)。然后dyn_threshold 的效果類似于將 threshold 應用到經過高通濾波的原始圖像上(參見highpass_image)。dyn_threshold可以提取出物體的輪廓,其中物體的大小(直徑)由低通濾波器的掩碼大小和物體邊緣的振幅決定:
所選擇的模板越大,找到的region就會越大。一般來說,模板的大小應該是我們要提取的物體直徑大小的兩倍左右。還有很重要的一點是最好不要把Offset這個變量設置為0,因為這樣會導致最后找到太多很小的regions,而這基本上都是噪聲。所以這個值最好是在5-40之間,值選擇的越大,提取出來的regions就會越小。
經過dyn_threshold這個算子處理之后,我們就可以提取一個物體的輪廓了,具體提取的方法當然要用到什么類似select_shape之類的算子,當然,這里最重要的是gen_contour_region_xld這個算子,用你剛才提取出來的這些區域生成XLD輪廓線,這樣就達到了提取物體輪廓的目的。 注意,我們這樣提取出來的所有符合條件的像素點都會被返回到一個region中去,所以如果你要分開的區域的話,就用connection這個算子再計算一下就好啦。
小結:
threshold是最簡單的閾值分割算子,理解最為簡單;binary_threshold是自動閾值算子,它可以自動選出暗(dark)的區域,或者自動選出亮(light)的區域,理解起來也沒有難度。
動態閾值算子dyn_threshold理解起來稍微復雜一點,使用dyn_threshold算子的步驟基本是這樣的:
① 將原圖進行濾波模糊處理。
② 用原圖和模糊后的圖逐個像素做比較,它可以根據參數分割出原圖比模糊后的圖灰度高(或者低)若干個灰度值的區域。
舉例如下:
處理代碼:
程序分析:本例中,將圖片模糊后,點陣字的黑色擴散了,隨之就是字的黑色不如原圖那么黑了,那么通過給定的限值“10”和“dark”,就可以將原圖比模糊后的圖暗10個灰階以上的區域(即黑色文字部分)選出來了。
4.var_threshold算子-均值和標準偏差局部閾值分割
Halcon閾值化算子dual_threshold和var_threshold的理解
var_threshold(Image : Region : MaskWidth, MaskHeight, StdDevScale, AbsThreshold, LightDark : )
——均值和標準偏差局部閾值分割,能夠較好的分開目標和背景,對不適合的參數設置不敏感。
- MaskWidth、 MaskHeight 是用于濾波平滑的掩膜單元;
- StdDevScale 是標準差乘數因子(簡稱標準差因子);
- AbsThreshold 是設定的絕對閾值;
- LightDark 有4個值可選,’light’、’dark’、’equal’、’not_equal’。
var_threshold圖像灰度值在均值與方差之和以上或在均值與方差之差以下
1)應用示例
var threshold (Image, Region, 4, 4, 0.2, 12, 'dark' )在該程序中,先用4x4的掩膜在圖像上逐像素游走,用原圖中的當前像素和對應掩膜中16個像素的灰度均值對比,找出暗(dark)的區域。當原圖像素灰度比對應的掩膜灰度均值低(0.2,12)個灰階時(本程序中StdDevScale = 0.2, AbsThreshold = 12),該區域被分割出來。
問題的關鍵就是理解如何通過StdDevscale和AbsThreshold來確定用于分割的閾值。
2)var_threshold的幫助文檔
- 1)d(x,y)指的是遍歷每個像素時,掩膜覆蓋的那些像素塊(本例中是4×4 = 16個像素)灰度的標準差;StdDevScale 是標準差因子;
- 2)當標準差因子StdDevscale>=0時, v(x.y)取(StdDevscale x 標準差)和AbsThreshold中較大的那個 ;
- 3)當標準差因子StdDevScale<= 0時, v(xy)取(StdDevscale x 標準差)和AbsThreshold中較小的那個。
實測發現,這里的比較大小是帶符號比較,由于標準差是非負數,當StdDevscale <0時,(StdDevscalex標準差) <=0恒成立,所以此時的取值就是(StdDevScale x標準差) 。
-
幫助文檔中StdDevscale的推薦值范圍是-1-1,一般通過上面的例子可知,一般的明顯的黑白過度處的在50左右,StdDevScale即-50 ~50 ,50的灰度差異,對于一般分割來說足夠。
-
標準差文檔還說:推薦的值是0.2,如果參數StdDevScale太大,可能分割不出任何東西;如果參數StdDevScale太小(例如-2) ,可能會把整個圖像區域全部輸出,也就說達不到有效分割的目的。一般推薦使用該算子時,StdDevScale取正值。
-
需要強調的是:在黑白過渡處,一般掩膜覆蓋的像素的標準差較大,而在其他平緩的地方,標準差較小;因此最終采用的分割值隨著掩膜在不斷遍歷像素的過程中,在(StdDevScale x 標準差)和AbsThreshold之間不斷切換。
3)var_threshold和dyn_threshold的區別和聯系:
- var_threshold算子和dyn_threshold算子極為類似,不同的是var threshold集成度更高,并且加入了"標準差x標準差因子"這一變量。可以有效地減少噪聲對分割的影響
- dyn_threshold是將原圖和濾波平滑后的圖對比, var_threshold是將原圖和對應像素掩膜覆蓋的像素的平均,灰度值對比,在算子var_threshold中,如果參數StdDevScale=0,那么就可以用動態閾值的方式非常近似地模擬,以上兩種算法的效果,極為類似。
- 那么當StdDevScale > 0 時,var_threshold對比dyn_threshold還存在什么優點呢?我認為是在黑白過渡處能減少分割出不需要的區域的概率。(因為黑白過渡處標準差大,當然前提是StdDevScale 不能設置得太小)
5.dual_threshold-雙重閾值分割(有符號圖像的閾值算子)
dual_threshold(Image : RegionCrossings : MinSize, MinGray, Threshold : )
- MinSize 表示分割出來的區域的最小面積(即分割出來的面積要大于MinSize);
- MinGray 表示分割出來的區域對應的原圖中圖像像素的最高灰度大于MinGray設定值。
- threshold 灰度值小于閾值(或大于閾值)的區域被抑制;
- dual_threshold算子的缺陷:它只能分割出灰度值高的亮區域,不能分割出灰度值低的暗區域
源圖:
RegionCrossings1
RegionCrossings2
RegionCrossings3(齒輪右下角灰度值未超過216,故無法選取)
RegionCrossings4()
6.auto_threshold-自動全局閾值分割
auto_threshold(Image : Regions : Sigma : )
——根據直方圖確定閾值自動全局閾值分割
- 運行原理,
- 第一,計算灰度直方圖。
- 第二,高斯平滑后從直方圖提取最小值。
- 第三,根據提取的最小值進行閾值分割。sigma越大提取區域越少。
7.fast_threshold-快速全局閾值分割
fast_threshold(Image : Region : MinGray, MaxGray, MinSize : )
——快速全局閾值分割
- 灰度值滿足MinGray<=g<=MaxGra聚合為一個區域,為了節省時間按兩步執行。
- 第一,先處理行列間隔Minsize的所有像素點。
- 第二,處理上一步選擇點的領域。和threshold相比分割速度快。
8.watersheds-分水嶺算法分割
watersheds(Image : Basins, Watersheds : : )
——分水嶺圖像分割。可以分割出分水嶺和盆地。
watersheds_threshold(Image : Basins : Threshold : )
——通過閾值實現圖像的分水嶺算法分割
第1步:
通過分水嶺算法watersheds()獲取圖像的盆地。
第2步:
根據第一步分水嶺算法分離結果,若盆地部分的灰度**< threshold**,則被合并到一起。設B1和B2分別為相鄰盆地的最小灰度值,W為將盆地分割為兩個盆地的最小灰度值。則分割結果為:
總結
以上是生活随笔為你收集整理的Halcon算子学习:图像阈值分割-threshold、binary_threshold、dyn_threshold算子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python画PR曲线(precisio
- 下一篇: MapReduce分析NCDC 年气象数