文章鏈接:http://blog.csdn.net/kk55guang2/article/details/78490069
頂帽變換和底帽變換
灰度級圖像 f 的頂帽變換(top-hat transformation)定義為f減去其開操作:
That(f)=f−(f∘b)
類似地,f 的底帽變換(bottom-hat transformation)定義為f的閉操作減去f:
Bhat(f)=(f∙b)−f
這兩個變換的主要應用之一是,用一個結構元通過開操作或閉操作從一副圖像中刪除物體,而不是擬合被刪除的物體。然后,差操作得到一副僅保留已刪除分量的圖像。頂帽變換用於暗背景上的亮物體,而底帽變換則用於相反的情況。由於這一原因,當談到這兩個變換時,常常分別稱為白頂帽變換和黑底帽變換。它們一個重要用途是校正不均勻光照的影響。[1]
實例
下面,我們通過一個實例來說明此方法,對於圖1(a),可以看到光照明顯不均勻,左邊光照更強,直接進行otsu法全局閾值得到圖1(b),可以看到左邊的硬幣分割出錯。
由於原圖是背景亮,前景暗,對原圖進行底帽變換以解決光照不均勻的問題,這里先給出處理結果,如圖1(c)和(d),可以看到底帽變換后的圖像刪除了大部分非均勻背景,最后閾值處理后,左邊的硬幣被分割出來,有少量殘缺,但是影響不大,后續可以通過形態學的其他處理將殘缺補齊。
圖1 處理圖像
那么為什么底帽變換或頂帽變換可以達到上述效果呢,下面以底帽變換為例,通過圖像的灰度三維圖來進行解釋。
底帽變換為f的閉操作減去f,閉運算可以幾何意義是讓球體緊貼在曲面的上表面滾動,此時球體任何部分所能達到的最低點即構成了閉運算f∙bf∙b的曲面。[2]
圖2為原圖灰度三維圖,上方彎曲的走勢顯示了圖像各部分光照不均勻造成的背景灰度不均現象,其中凹陷對應圖像中灰度值比較小的區域,也就是圖像中的硬幣。
通過選取大於硬幣大小的合適結構元,可以看成一個球體在灰度曲面上滾動,球體下表面的軌跡構成閉運算的曲面,如圖3所示,原圖中的凹陷都被填上,可以近似代表不均勻的背景。閉運算完之后再減去原圖像即可得到背景近似均勻的圖像,如圖4所示,對應的灰度圖可以看圖1(c),可以看到不均勻的背景被大致去除,這將十分有助於后面的閾值分割。
參考程序:
//Image_Use為原圖像,Image為處理圖像副本 for (int i = 0; i < Use_ROWS; i++) { for (int j = 0; j < Use_Line; j++) { Image[i][j] = Image_Use[i][j]; } } //二值化 int i,j; int Threshold; Threshold = GetOSTU(Image); for(i = 0; i < Use_ROWS; i++) { for(j =0; j < Use_Line; j++) { if(Image[i][j] >= Threshold) Image[i][j]=255; else Image[i][j]=0; } } //去噪:不處理四邊 int bai; for(i = 1; i < Use_ROWS-1; i++) { for( j=1; j < Use_Line-1; j++) { if(Image[i][j] == 255) continue; bai = Image[i-1][j] + Image[i-1][j-1] + Image[i-1][j+1] +Image[i][j+1] +Image[i][j-1] +Image[i+1][j] +Image[i+1][j-1] +Image[i+1][j+1] ; if(bai == 2040) Image[i][j] = 255; } } //開操作 for (int i = 1; i < Use_ROWS-1; i++) { for (int j = 1; j < Use_Line - 1; j++) { if (Image[i][j] == 255 && Image[i][j + 1] == 255 && Image[i][j - 1] == 255) { Image[i][j] = 255; } } } for (int i = 1; i < Use_ROWS-1; i++) { for (int j = 1; j < Use_Line - 1; j++) { if (Image[i][j] == 255 || Image[i][j + 1] == 255 || Image[i][j - 1] == 255) { Image[i][j] = 255; } } } //原圖像-開操作 for (int i = 0; i < Use_ROWS; i++) { for (int j = 0; j < Use_Line; j++) { Image_Use[i][j] = Image_Use[i][j] - Image[i][j]; } } //再進行頂帽變換的圖像進行二值化 Threshold = GetOSTU(Image_Use); for(i = 0; i < Use_ROWS; i++) { for(j =0; j < Use_Line; j++) { if(Image_Use[i][j] >= Threshold) Image_Use[i][j]=255; else Image_Use[i][j]=0; } } //去噪:不處理四邊 for(i = 1; i < Use_ROWS-1; i++) { for( j=1; j < Use_Line-1; j++) { if(Image_Use[i][j] == 255) continue; bai = Image_Use[i-1][j] + Image_Use[i-1][j-1] + Image_Use[i-1][j+1] +Image_Use[i][j+1] +Image_Use[i][j-1] +Image_Use[i+1][j] +Image_Use[i+1][j-1] +Image_Use[i+1][j+1] ; if(bai == 2040) Image_Use[i][j] = 255; } }
參考文獻
[1]《數字圖像處理》(第3版),岡薩雷斯著,阮秋琦譯,電子工業出版社,2013年;
[2]《數字圖像處理與機器視覺——Visual C++與Matlab實現》,張錚,王艷平,薛桂香等編著,人民郵電出版社,2014年