圖像的對比度增強算法在很多場合都有着重要的應用,特別是在醫學圖像上,這是因為在眾多疾病的診斷中,醫學圖像的視覺檢查時很有必要的。而醫學圖像由於本身及成像條件的限制,圖像的對比度很低。因此,在這個方面已經開展了很多的研究。這種增強算法一般都遵循一定的視覺原則。眾所周知,人眼對高頻信號(邊緣處等)比較敏感。雖然細節信息往往是高頻信號,但是他們時常嵌入在大量的低頻背景信號中,從而使得其視覺可見性降低。因此適當的提高高頻部分能夠提高視覺效果並有利於診斷。
在這一方面,傳統的線性對比度拉升以及直方圖均衡化是使用的最為廣泛的全局圖像增強方法。對比度拉升線性的調整了圖像的動態范圍,而直方圖均衡化棲利用累計直方圖分布概率重新映射圖像的數據。這些方法雖然簡單,但是都沒有考慮到局部的信息。並且,全局直方圖均衡化(GHE)還會產生使得一些噪音過度加強。
在局部對比度增強方面,有兩種方式是最為有名的,一種是自適應直方圖均衡化(AHE),這個算法可以參考我的博文限制對比度自適應直方圖均衡化算法原理、實現及效果。還有一種就是自適應對比度增強(ACE)。AHE算法使用局部的直方圖的相關信息對數據進行映射。這改變了圖像的對比度,但是需要大量的計算。后來有人利用了雙線性差值技術克服了這個問題,首先將圖像分塊,然后分別計算這些快內部的映射關系。為了增強某一個像素點的值,映射關系通過與這個像素所在塊相鄰的四個塊的映射關系差值獲得。在這個算法中,僅僅需要一個塊大小的參數(在我的博文中還對參數進行了擴展)。
ACE算法采用了反銳化掩模技術,我們對此過程解釋如下:首先圖像被分成兩個部分。一是低頻的反銳化掩模(unsharp mask)部分,可以通過圖像的低通濾波(平滑,模糊技術)獲得。二是高頻成分,可以過原圖減去反銳化掩模獲取。然后高頻部分被放大(放大系數即為對比度增益CG)並加入到反銳化掩模中去,最后得到增強的圖像。ACE算法的核心就是如何計算CG,這里將介紹兩種簡單的CG計算方法。
在繼續說明之前,先貼一幅這個算法處理的圖給大家看看效果,免得都是通篇的文字。
原圖 處理后的圖
在談及CG之前,我們還是需要看看一些基礎的工作。首先上面談到了unsharp mask,他對應於圖像的低頻成分。對於具體的像素,一般可以通過計算以該像素為中心的局部區域的像素平均值來實現。我們假定x(i,j)是圖像中某點的灰度值,局部區域的定義為:以(i,j)為中心,窗口大小為(2n+1)*(2n+1)的區域,其中n為一個整數。當然這個窗口區域也不一定就要是正方形。局部的平均值,也就是低頻部分,可以用下式計算:
而局部方差為:
上式中σx(i,j)就是所謂的局部標准差(LSD)。定義f(i,j)表示x(i,j)對應的增強后的像素值。則ACE算法可以表示如下:
其中的函數G(i,j)就是上文所講的CG。一般情況下CG總是大於1的,這樣高頻成分就能得到增強。
關於CG的取值,一種最簡單的方式就是令其為常量,假定為C,一般C>1,這樣式3就變為:
這種情況下,圖像中所有的高頻部分都被同等放大,可能有些高頻部分會出現過增強的現象的。
原圖 n=50,c=2 n=50,c=3
在上圖中,分別使用了C=2及C=3的的情況,在C=3時,可見星球邊緣的部分被過增強,出現成片的白色。
一種解決的方案就是使用不同的增益。Lee等人提出了如下的方案:
上式中,D是個常數,這樣,CG是空間自適應的,並且和局部均方差成反比,在圖像的邊緣或者其他變化劇烈的地方,局部均方差比較大,因此CG的值就比較小,這樣就不會產生振鈴效應。然而,在平滑的區域,局部均方差就會很小,這樣CG的值比較大,從而引起了噪音的放大,所以需要對CG的最大值做一定的限制才能獲得更好的效果。
D這個常數的取值有些文章介紹說用圖像的全局平均值,我編程的時候是用的圖像的全局均方差,並且增加一個參數Amount,用來再次控制高頻增強的程度。
對式我們進行了編程,並測試一些圖像,當進行一些參數的調整時,都能獲得比較理想的增強效果,舉例如下:
原圖 n=20,Amount=100,MaxCG=3 n=20,Amount=100,MaxCG=10
原圖 n=25,Amount=100,MaxCG=2 n=50,Amount=150,MaxCG=2
原圖 n=50,Amount=150,MaxCG=3 n=50,Amount=150,MaxCG=10
不僅是對醫學圖像,對於我日常生活中的一些不是很理想的圖片,經過上述ACE算法在大部分情況下也可獲得較好的效果:
為什么要對CG的最大值進行限制,我們舉下面這個圖作為例子:
原圖 n=50,Amount=150,CG不限制
在上圖中,圖像右上角部位屬於平滑區域,但是仔細觀察有着微弱的層次感,如果不對CG進行限制,則由於LSD的值很小,導致CG的值特別大,從而產生像素飽和的現象(即像素的值超過了255)。如右圖所示,解決這個問題一種方法就是增加n的值,即增加取樣半徑,通過取樣半徑的增加,使得以平滑區域為中心的窗口能夠覆蓋一些非平滑的區域,從而產生較大的LSD值。另外一種就是采用CG限幅的方式,效果如下:
n=200,Amount=150,CG不限制 n=50,Amount=150,CG<3
針對不同的圖像,要想獲得理想的效果,可能還是需要人工的去參與和調整這些參數,我目前尚未發現能自動確定這些參數的文章。
根據公式5,是不難寫出實現代碼的,但還要實用,主要的難點還是如何實現快速的計算,因為隨着取樣半徑n的增加,每個像素點涉及到的區域范圍就越廣,計算量會直線上升,因此需要采用優化的策略。
均值模糊的優化已經有了很多成熟的方案,普遍的就是先行均值,在列均值,當然還有更好的優化方式。
而計算局部均方差,則需要一定的水平了,但是同樣的原理還是利用每變換一次都有很多的重疊的部分的數據,這個等有空了我會專門寫篇文章的。
雖然采用了優化算法,但是實際上這個算法還是有點慢的,主要原因還是計算均方差確實有點耗時,並且優化的算法也是下一行像素的結果值依賴於前一行的計算結果,而對於第一行是需要進行特殊處理的,因此,這個使用GPU計算也是很難進一步進行優化的。
但是優化后的算法執行時間和n基本是沒有關系的。
同樣,提供個編譯好的文件給有興趣研究該算法的朋友看看效果:http://files.cnblogs.com/Imageshop/LocalAreaContrastEnhance.rar
當然,這個算法不是對任何圖像都能產生正能量,那些本來就很好的圖,你用它只會適得其反。
參考論文:Real-Time Adaptive Contrast Enhancement
2013.10.19 日補充:
今日對改算法又進行了一些測試,發現其對霧天圖像,或者比較昏暗的圖像都有很好的增強作用,再補充一些測試圖像的例子:
抽空用C++寫了個標准的DLL,結合OpenMp工具對算法實現了多線程運行,執行速度上比C#的多線程版本要快那么一點點的。
DLL的接口函數函數如下:
[DllImport("LocalAreaContrastEnhance.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true)] private static extern void LocalAreaContrastEnhance(byte* Scan0, int Width, int Height, int Stride, int Radius, int Amount, int MaxCG);
注意我只實現了24位的算法。
再上傳一個C#調用該DLL的代碼示例:http://files.cnblogs.com/Imageshop/LocalAreaContrastEnhanceTest.rar
*********************************作者: laviewpbt 時間: 2013.8.23 聯系QQ: 33184777 轉載請保留本行信息************************