搬運自本人 CSDN 博客:https://blog.csdn.net/ajianyingxiaoqinghan/article/details/71435098
注:由于簡書不支持 Latex 公式在 Markdown 中的顯示,所以文中用 $ 包圍的公式不能正常顯示,請移步本人 CSDN 博客查看原文。
Retinex圖像增強算法(SSR, MSR, MSRCR)詳解及其OpenCV源碼
Retinex是一種常用的建立在科學實驗和科學分析基礎上的圖像增強方法,它是Edwin.H.Land于1963年提出的。就跟Matlab是由Matrix和Laboratory合成的一樣,Retinex也是由兩個單詞合成的一個詞語,他們分別是retina 和cortex,即:視網膜和皮層。Land的retinex模式是建立在以下三個假設之上的:
- 真實世界是無顏色的,我們所感知的顏色是光與物質的相互作用的結果。我們見到的水是無色的,但是水膜—肥皂膜卻是顯現五彩繽紛,那是薄膜表面光干涉的結果。
- 每一顏色區域由給定波長的紅、綠、藍三原色構成的;
- 三原色決定了每個單位區域的顏色。
Retinex理論的基礎理論是物體的顏色是由物體對長波(紅色)、中波(綠色)、短波(藍色)光線的反射能力來決定的,而不是由反射光強度的絕對值來決定的,物體的色彩不受光照非均勻性的影響,具有一致性,即retinex是以色感一致性(顏色恒常性)為基礎的。不同于傳統的線性、非線性的只能增強圖像某一類特征的方法,Retinex可以在動態范圍壓縮、邊緣增強和顏色恒常三個方面達到平衡,因此可以對各種不同類型的圖像進行自適應的增強。
40多年來,研究人員模仿人類視覺系統發展了Retinex算法,從單尺度Retinex算法,改進成多尺度加權平均的MSR算法,再發展成彩色恢復多尺度MSRCR算法。筆者在本文中,從原理闡述算法的流程,并提供源碼地址。
參考鏈接:
http://blog.csdn.net/carson2005/article/details/9502053
http://www.cnblogs.com/Imageshop/archive/2013/04/17/3026881.html
參考論文:
《一種結合直方圖均衡化和MSRCR的圖像增強新算法》——李錦 等人
一. 單尺度SSR(Single Scale Retinex)
1. 原理
一幅給定的圖像S(x,y)可以分解為兩個不同的圖像:反射圖像R(x,y)和入射圖像(也有人稱之為亮度圖像)L(x,y),其原理圖如下所示:
如上圖所示,圖像可以看做是入射圖像和反射圖像構成,入射光照射在反射物體上,通過反射物體的反射,形成反射光進入人眼。最后形成的圖像可以如下公式表示:
$$r(x, y) = logR(x, y) = log \frac{S(x, y)}{L(x, y)}$$
其中,<code>R(x, y)</code>表示了物體的反射性質,即圖像內在屬性,我們應該最大程度的保留;而<code>L(x, y)</code>表示入射光圖像,決定了圖像像素能達到的動態范圍,我們應該盡量去除。
一般,我們把照射圖像假設估計為空間平滑圖像,原始圖像為<code>S(x, y)</code>,反射圖像為<code>R(x, y)</code>,亮度圖像為<code>L(x, y)</code>,可以得出上面的公式(1),以及下面的公式:
$r(x, y) = logR(x, y) = log \frac{S(x, y)}{L(x, y)}$ ............(2)
$r(x, y) = \log S(x, y) - \log [F(x, y) \bigotimes S(x, y) ]$ .............(3)
這里,<code>r(x, y)</code>是輸出圖像,式(3)中后面中括號里的運算是卷積運算。<code>F(x, y)</code>是中心環繞函數,表示為:
$F(x, y) = \lambda e{\frac{-(x2 + y2)}{c{2}}}$ .............(4)
式(4)中的C是<font color=red>高斯環繞尺度</font>,λ是一個尺度,它的取值必須滿足下式:
$\int \int F(x, y)dxdy = 1$ .............(5)
上面的式中可以看出,SSR算法中的卷積是對入射圖像的計算,其物理意義是通過計算像素點與周圍區域在加權平均的作用下,估計圖像中照度的變化,并將$L(x, y)$去除,只保留$S(x, y)$屬性。
2. 算法的實現流程
單尺度Retinex算法SSR的實現流程可以概括如下:
- 讀原圖S(x, y):
- 若原圖為灰度圖:將圖像各像素的灰度值由整數型(int)轉換為浮點數(float),并轉換到對數域;
- 若原圖為彩色圖:將顏色分通道處理,每個分量像素值由整數型(int)轉換為浮點數(float),并轉換到對數域;
- 輸入高斯環繞尺度C,把積分運算離散化,轉為求和運算,通過上式(4)(5)確定λ的值;
- 由式(3)得<code>r(x, y)</code>;
- 若原圖是灰度圖,則只有一個<code>r(x, y)</code>;
- 若原圖為彩色圖,則每個通道都有一個對應的<code>r(x, y)</code>;
- 將<code>r(x, y)</code>從對數域轉換到實數域,得到輸出圖像<code>R(x, y)</code>;
- 此時的<code>R(x, y)</code>值的范圍并不是0--255,所以還需要進行線性拉伸并轉換成相應的格式輸出顯示。
前面的公式中,中心環繞函數<code>F(x, y)</code>用的是低通函數,這樣能夠在算法中估計出入射圖像對應原始圖像的低頻部分。從原始圖像中除去低頻照射部分,就會留下原始圖像所對應的高頻分量。高頻分量很有價值,因為在人類的視覺系統中,人眼對邊緣部分的高頻信息相當敏感,所以SSR算法可以較好的增強圖像中的邊緣信息。
由于SSR算法中所選用的高斯函數特點,對于動態范圍大幅度壓縮和對比度增強兩個指標,增強后的圖像不能同時保證。但是為了平衡兩種增強效果,就必須選擇一個較為恰當的高斯尺度常量C。C值一般取值在80--100之間。
3. OpenCV源碼
見源碼附錄的Retenix()函數。
二. 多尺度MSR(Multi-Scale Retinex)
1. 原理
MSR是在SSR基礎上發展來的,優點是可以同時保持圖像高保真度與對圖像的動態范圍進行壓縮的同時,MSR也可實現色彩增強、顏色恒常性、局部動態范圍壓縮、全局動態范圍壓縮,也可以用于X光圖像增強。
MSR計算公式如下:
$ r(x, y) = \sum_{k}^{K}w_{k} { \log S(x, y) - \log [F_{k}(x, y) \cdot S(x, y) ] } $ ............(6)
式中,K是高斯中心環繞函數的個數。當K=1時,MSR退化為SSR。
通常來講,為了保證兼有SSR高、中、低三個尺度的優點來考慮,K取值通常為3,且有:
$ w_{1} = w_{2} = w_{3} = \frac{1}{3} $ ............(7)
此外,實驗表明,ci分別取15, 80, 200可以得到較好效果。
一般的Retinex算法對光照圖像估計時,都會假設初始光照圖像是緩慢變化的,即光照圖像是平滑的。但實際并非如此,亮度相差很大區域的邊緣處,圖像光照變化并不平滑。所以在這種情況下,Retinuex增強算法在亮度差異大區域的增強圖像會產生光暈。
另外MSR常見的缺點還有邊緣銳化不足,陰影邊界突兀,部分顏色發生扭曲,紋理不清晰,高光區域細節沒有得到明顯改善,對高光區域敏感度小等。
2. 效果對比
對于SSR與MSR的效果如下所示:
3. OpenCV源碼
見源碼附錄的MultiScaleRetinex()函數。
三. 帶顏色恢復的MSR方法MSRCR(Multi-Scale Retinex with Color Restoration)
在以上的兩幅測試圖像中,特別是第二幅,我們看到明顯的偏色效果,這就是SSR和MSR普遍都存在的問題。
為此,研究者又開發出一種稱之為帶色彩恢復的多尺度視網膜增強算法(MSRCR,Multi-Scale Retinex with Color Restoration) ,具體討論的過程詳見《A Multiscale Retinex for Bridging the Gap Between Color Images and the Human Observation of Scenes》論文。
1. 原理
在前面的增強過程中,圖像可能會因為增加了噪聲,而使得圖像的局部細節色彩失真,不能顯現出物體的真正顏色,整體視覺效果變差。針對這一點不足,MSRCR在MSR的基礎上,加入了色彩恢復因子C來調節由于圖像局部區域對比度增強而導致顏色失真的缺陷。
改進算法如下所示:
$ R_{MSRCR_{i}}(x, y) = C_{i}(x, y) R_{MSR_{i}}(x, y) $ ............(8)
$ C_{i}(x, y) = f[I_{i}^{'}(x, y)] = f[\frac{I_{i}(x, y)}{ \sum_{j=1}^{N} I_{j}(x, y)}] $ ............(9)
$ f[I_{i}^{'}(x, y)] = \beta \log [\alpha I_{i}^{'}(x, y)] = \beta { \log [\alpha I_{i}^{'}(x, y)] - \log [\sum_{j=1}^{N}I_{j}(x, y)] } $ ............(10)
其中參數說明如下:
- Ii(x, y)表示第i個通道的圖像
- Ci表示第i個通道的彩色回復因子,用來調節3個通道顏色的比例;
- f(·)表示顏色空間的映射函數;
- β是增益常數;
- α是受控制的非線性強度;
MSRCR算法利用彩色恢復因子C,調節原始圖像中3個顏色通道之間的比例關系,從而把相對較暗區域的信息凸顯出來,達到了消除圖像色彩失真的缺陷。
處理后的圖像局部對比度提高,亮度與真實場景相似,在人們視覺感知下,圖像顯得更加逼真。
但是MSRCR算法處理圖像后,像素值一般會出現負值。所以從對數域<code>r(x, y)</code>轉換為實數域<code>R(x, y)</code>后,需要通過改變增益Gain,偏差Offset對圖像進行修正。使用公式可以表示為:
$ R_{MSRCR_{i}}(x, y)' = G\cdot R_{MSRCR_{i}}(x, y) + O $ ............(11)
式(11)中,G表示增益Gain,O表示偏差Offset。它們的值取決于軟件中的算法實現。
2. MSRCR其他實現方法
MSRCR方法如上,且獲得了不錯的效果。但在博文《MSRCR》中,作者認為論文里的方法不起任何作用,并且論文里為了這個又引入了太多的可調參數,增加了算法的復雜性,不利于自動化實現。
博文作者認為,GIMP的contrast-retinex.c文件里使用的算法很好,效果也很好。他直接從量化的方式上入手,引入了均值和均方差的概念,再加上一個控制圖像動態的參數來實現無色偏的調節過程,簡要描述如下:
- 計算出 log[R(x,y)]中R/G/B各通道數據的均值Mean和均方差Var(注意是均方差)。
- 類似下述公式計算各通道的Min和Max值。
- Min = Mean - Dynamic * Var;
- Max = Mean + Dynamic * Var;
- 對Log[R(x,y)]的每一個值Value,進行線性映射:
R(x,y) = ( Value - Min ) / (Max - Min) * (255 - 0), 同時要注意增加一個溢出判斷,即:
- if (R(x, y) > 255) R(x,y) = 255;
- else if (R(x,y) < 0) R(x,y) = 0;
就是經過這么簡單的處理,實踐證明可以取得非常好的效果,下面貼出一些處理后的效果。
由以上三幅圖的效果得出的結論:
- MSRCR效果要比MSR好很多,基本消除了色偏。
- 對于MSRCR,尺度數對結果的影像不是特別大,但是隨著尺度數的增加,算法耗時會線性增加,因此,一般尺度數取3就較為合適了。
繼續做比較:
由以上三幅圖的效果得出的結論:
- Dynamic取值越小,圖像的對比度越強。
- 一般來說Dynamic取值2-3之間能取得較為明顯的增強效果,即能取得很自然過渡效果,又能保持圖像的清晰度適度增強。
關于尺度,個人建議取值以大于100為佳。
retinex算法的效果對于一些正常的圖像處理后的效果并不佳,我們可以認為它就是為那些在外界環境不理想的狀態下拍攝的圖像增強而設計的,如對于航拍的霧天圖片,醫學上的成像圖片等成像條件惡劣的圖有很明顯的效果。筆者的畢業設計涉及了水下圖像的修復,水下圖像相對于空氣中成像性低,應該會有很大的效果。
NASA在處理航天相關照片時也使用了Retinex技術。關于NASA對Retinex技術的應用,可以參考:http://dragon.larc.nasa.gov/retinex/
關于GIMP的實現代碼,筆者提供從網上找到的鏈接。如果要想完全看懂代碼的意思很難,但算法部分還是不難提取的(不過筆者也懶得把它移植到OpenCV上……)下載鏈接如下;
http://files.cnblogs.com/Imageshop/contrast-retinex.rar
四. Retinex圖像增強算法的其他算法
先貼出前面MSRCR的基本公式如下:
<img src="http://chart.googleapis.com/chart?cht=tx&chl= $$ R_{MSR_{i}} = \sum_{n=1}^{N}w_{n}R_{n_{i}} = \sum_{n=1}^{N} w_{n} { \log I_{i}(x, y) - \log (F_{n}(x, y) * I_{i}(x, y)) } $$
" style="border:none;">
............(10)
上式參數意義如下:
- I為原始輸入圖像;
- F是濾波函數(一般為高斯函數);
- N為尺度的數量;
- W為每個尺度的權重(一般都為1/N)
- R表示在對數域的圖像的輸出;
由于其中的R是對數域的輸出,所以要轉換為實數域的數字圖像,必須要將其量化為[0, 255]的范圍。這個量化算法很重要,它直接決定了最終輸出圖像的品質。
目前結合一些文章中提出的過程,有四種方法處理:
第一種方法:直接線性量化:
公式如下:
$$ R_{MSRCR_{i}}(x, y) = 255 \frac{R_{MSRCR_{i}}(x, y) - min_{i}(min_{(x, y)} R_{MSRCR_{i}}(x, y))}{max_{i}(max_{(x, y)} R_{MSRCR_{i}}(x, y) - min_{i}(min{(x, y)} R_{MSRCR_{(x, y)}}))} $$
............(12)
由于Retinex數據處理后的高動態特性,所以這種方式處理后,數據分布很廣,會出現嚴重兩極化現象,一般情況難以得到滿意的結果。
第二種方法:經典Canonical Gain/Offset算法:
即在經典MSRCR文章《A Multiscale Retinex for Bridging the Gap Between Color Images and the Human Observation of Scenes》論文中提到的算法。公式如下:
$ R_{MSRCR_{i}}(x, y) = G [R_{MSRCR_{i}}(x, y) - b] $ ............(13)
式(12)中的G與b均為經驗參數。
第三種方法:自動色階方法:
該方法的處理類似于Photoshop中的自動色階,將數據按照一定百分比去除最大最小部分,然后中間部分重新線性量化到0--255之間。
第四種方法:GIMP的Retinex算法:
詳見前文上文:三.2.MSRCR其他實現方法
五. OpenCV源碼
筆者整理了OpenCV源碼,在代碼中做了中英文注釋,并已經將源碼上傳到了我的GitHub賬戶上。筆者的OpenCV版本是2.4.9。
文件夾下載完畢后,終端進入其根目錄執行指令即可:
cmake ./
make