matlab Retinex图像增强算法
Retinex理論在彩色圖像增強(qiáng)、圖像去霧、彩色圖像恢復(fù)方面擁有很好的效果,下面介紹一下我對該算法的理解。
Retinex理論
Retinex理論始于Land和McCann于20世紀(jì)60年代作出的一系列貢獻(xiàn),其基本思想是人感知到某點的顏色和亮度并不僅僅取決于該點進(jìn)入人眼的絕對光線,還和其周圍的顏色和亮度有關(guān)。Retinex這個詞是由視網(wǎng)膜(Retina)和大腦皮層(Cortex)兩個詞組合構(gòu)成的.Land之所以設(shè)計這個詞,是為了表明他不清楚視覺系統(tǒng)的特性究竟取決于此兩個生理結(jié)構(gòu)中的哪一個,抑或是與兩者都有關(guān)系。
Land的Retinex模型是建立在以下的基礎(chǔ)之上的:
一、真實世界是無顏色的,我們所感知的顏色是光與物質(zhì)的相互作用的結(jié)果。我們見到的水是無色的,但是水膜—肥皂膜卻是顯現(xiàn)五彩繽紛,那是薄膜表面光干涉的結(jié)果;
二、每一顏色區(qū)域由給定波長的紅、綠、藍(lán)三原色構(gòu)成的;
三、三原色決定了每個單位區(qū)域的顏色。
Retinex 理論的基本內(nèi)容是物體的顏色是由物體對長波(紅)、中波(綠)和短波(藍(lán))光線的反射能力決定的,而不是由反射光強(qiáng)度的絕對值決定的;物體的色彩不受光照非均性的影響,具有一致性,即Retinex理論是以色感一致性(顏色恒常性)為基礎(chǔ)的。如下圖所示,觀察者所看到的物體的圖像S是由物體表面對入射光L反射得到的,反射率R由物體本身決定,不受入射光L變化。
圖1.Retinex理論中圖像的構(gòu)成
Retinex理論的基本假設(shè)是原始圖像S是光照圖像L和反射率圖像R的乘積,即可表示為下式的形式:
基于Retinex的圖像增強(qiáng)的目的就是從原始圖像S中估計出光照L,從而分解出R,消除光照不均的影響,以改善圖像的視覺效果,正如人類視覺系統(tǒng)那樣。在處理中,通常將圖像轉(zhuǎn)至對數(shù)域,即,從而將乘積關(guān)系轉(zhuǎn)換為和的關(guān)系:
Retinex方法的核心就是估測照度L,從圖像S中估測L分量,并去除L分量,得到原始反射分量R,即:
函數(shù)實現(xiàn)對照度L的估計(可以去這么理解,實際很多都是直接估計r分量)。
Retinex理論的理解
如果大家看論文,那么在接下去的篇幅當(dāng)中,肯定會介紹兩個經(jīng)典的Retinex算法:基于路徑的Retinex以及基于中心/環(huán)繞Retinex。在介紹兩個經(jīng)典的Retinex算法之前,我先來講一點個人的理解,以便第一次接觸該理論的朋友能夠更快速地理解。當(dāng)然,如果我的理解有問題,也請大家?guī)兔χ赋觥?/p>
Retinex理論就我理解,與降噪類似,該理論的關(guān)鍵就是合理地假設(shè)了圖像的構(gòu)成。如果將觀察者看到的圖像看成是一幅帶有乘性噪聲的圖像,那么入射光的分量就是一種乘性的,相對均勻,且變換緩慢的噪聲。Retinex算法所做的就是合理地估計圖像中各個位置的噪聲,并除去它。
在極端情況下,我們大可以認(rèn)為整幅圖像中的分量都是均勻的,那么最簡單的估計照度L的方式就是在將圖像變換到對數(shù)域后對整幅圖像求均值。因此,我設(shè)計了以下算法來驗證自己的猜想,流程如下:
(1) 將圖像變換到對數(shù)域?;
(2) 歸一化去除加性分量?;
(3) 對步驟3得到的結(jié)果求指數(shù),反變換到實數(shù)域。
這里為了簡化描述,省略了對圖像本身格式的變換,算法用Matlab實現(xiàn):
% ImOriginal:原始圖像 % type:'add'表示分量是加性的,如霧天圖像;'mult'表示分量是乘性的,如對照度的估計 [m,n,z] = size(ImOriginal); ImOut = uint8(zeros(m,n,z)); for i = 1:zif strcmp(type,'add')ImChannel = double(ImOriginal(:,:,i))+eps;elseif strcmp(type,'mult')ImChannel = log(double(ImOriginal(:,:,i))+eps);elseerror('type must be ''add'' or ''mult''');endImOut(:,:,i) = EnhanceOneChannel(ImChannel); end ImOut = max(min(ImOut,255), 0); end function ImOut = EnhanceOneChannel(ImChannel) % 計算計算單個通道的反射分量 % 1.對全圖進(jìn)行照射分量估計 % 2.減去照射分量 % 3.灰度拉伸 ImChannel = ImChannel./max(ImChannel(:)); ImRetinex = round(exp(ImChannel.*5.54)); ImOut = uint8(ImRetinex); end為了驗證算法的有效性,這里使用經(jīng)典的Retinex算法與我所用的算法進(jìn)行對比試驗,效果如下:
圖2.測試原圖
圖3.經(jīng)典Retinex算法結(jié)果
圖4.上述方法結(jié)果
從對比中可以看到,對于去除照度,還原圖像本身來講,效果還可以,并且不會在邊緣位置產(chǎn)生光暈現(xiàn)象。缺點就是在去除照度分量L過程中,保留的反射分量R我在上述算法中使用歸一化后直接進(jìn)行反變換。這一步的作用可以近似看成去除一個均勻的直流分量,即均勻的照度分量。由于操作都是全局的,這里默認(rèn)假設(shè)了所有位置的照射分量都是相同的,因此在灰度拉伸的時候沒有照顧到局部的特性,圖像整體亮度偏暗。當(dāng)然,全局的照度估計對于圖像的增強(qiáng)肯定有相當(dāng)?shù)木窒扌?#xff0c;其增強(qiáng)效果在色彩的還原和亮度處理等方面還是有一定缺陷的。
個人認(rèn)為,Retinex算法的關(guān)鍵還是正確的分析了噪聲的性質(zhì)。相信很多人都看到利用基于Retinex的圖像水下增強(qiáng)、基于Retinex的圖像去霧等等,我也好奇,那就試試吧。大霧圖片嘛誰沒有,前一陣子大霧天,沒事拍了幾張照片,終于用上了,請看對比圖:
圖5.有霧原圖
圖6.經(jīng)典Retinex去霧效果
圖7.上述方法去霧效果
還是老規(guī)矩,這時候?qū)Ρ仍囼炦€是最能說明效果的,為此選了一幅干擾很大的圖像。基本上各位要是顯示器比較差一點,從原圖當(dāng)中是很難看出大霧后面的東西。從去霧效果來看,上述方法的效果并不比經(jīng)典算法要差,至少在去霧的效果上,本實驗結(jié)果從主觀上給人的感覺還是不錯的。
在上述案例中,最重要的就是正確分析有霧圖像的結(jié)構(gòu),與Retinex理論一開始的核心思想有區(qū)別的是,在針對這種加性的干擾時,經(jīng)典的Retinex算法在處理過程中,其實僅僅是利用其估計加性的干擾分量;當(dāng)然,拋開Retinex理論對照度、反射率對最終圖像形成的核心思想(如圖1),后續(xù)最重要的就是對這個加性的干擾的估計了。
對于有霧的圖像,我們大可以看作透過一塊磨砂玻璃去看一幅清晰的圖像,這樣大家就能很好理解為什么認(rèn)為在這個案例中,將霧的干擾認(rèn)為是一個加性的了。諸如后面兩個經(jīng)典的算法,所有的這類算法歸根結(jié)底就是更好地利用原圖像中的像素點去估計原始照度。從上面例程上可以看出,使用一個全局估計對局部的增強(qiáng)是比較差的,如果存在照度不均勻(霧的濃度不均勻),或者背景顏色亮度很高等情況時,處理結(jié)果會趨向惡劣,效果比較差。
當(dāng)然,經(jīng)典也不是完美,從圖3中可以看到,經(jīng)典的算法容易出現(xiàn)光暈效果(藍(lán)色書本文字周圍一圈白色),因此后續(xù)對于照度估計和去除光暈等問題又有很多基于Retinex理論的變體算法,這里暫不進(jìn)行介紹。下面開始介紹兩個經(jīng)典的算法,查看Matlab代碼下載點擊:
http://www.cs.sfu.ca/~colour/publications/IST-2000/
McCann Retinex算法
McCann Retinex 算法是McCann和Frankle一起提出的一種Retinex算法,該算法是一種基于多重迭代策略的Retinex算法,單個點的像素值取決于一條特定路徑的環(huán)繞的結(jié)果,經(jīng)過多次迭代逼近理想值。通過比較螺旋式路徑上的各像素點的灰度值來估計和去除圖像的照度分量。
圖8.McCann Retinex算法路徑選擇示意圖
這個圖是參照人家論文的,不過我準(zhǔn)備像論文那樣講,因為太復(fù)雜了,不容易懂。從圖中我們可以看到,算法沿著這個螺旋式的路徑選取用于估計的點,并且越靠近預(yù)測的中心點選取的點數(shù)越多。這個從實際物理上也解釋的通,靠的近的像素點與中心像素點的相關(guān)性肯定要要比遠(yuǎn)處的點要高。
該算法估測圖像經(jīng)過以下幾個步驟:
1. 將原圖像變換到對數(shù)域,彩色圖像對各通道都進(jìn)行對數(shù)變換;
2. 初始化常數(shù)圖像矩陣,該矩陣作為進(jìn)行迭代運算的初始值;
3. 計算路徑,如上圖8所示,這里令為路徑上的點,從遠(yuǎn)到近排列;
4. 對路徑上的像素點按照如下公式運算:
公式所表示的大致意思為:從遠(yuǎn)到近,中心點像素值減去路徑上的像素值得到的差值的一半與前一時刻的估計值之間的和。最終,中心像素點的像素大致的形式為
其中表示中心位置最終的反射率估計,為常數(shù)值為轉(zhuǎn)換后的圖像中的最大值,在步驟2中被確定。從這里將按照Retinex理論進(jìn)行分解,最終公式中可以看到,最終照度分量被去除了,而中心位置的反射率由路徑上各點的反射率之間的差值進(jìn)行估計,并且從軌跡上可以看到,靠的越近的在最終估計的時候所占比重越大。
就我個人理解,這類估計算法,實質(zhì)是將中心位置和周圍亮度之間的差異作為最終中心位置的反射率的估計。如果中心位置亮度本身高,那么最終的結(jié)果還是高亮度的;如果中心位置亮度低,那么中心與其它點的差肯定是負(fù)值,最終的結(jié)果就比較小,亮度就比較低。這就要求路徑上的點需要能夠很好地代表整幅圖像的特性,如果圖像本身很規(guī)則,那么可能中央與周圍計算的結(jié)果無法估測該點像素本身的灰度特性,結(jié)果就與預(yù)期的可能不一樣了。如下圖9可以看到,算法實質(zhì)是估計中心和周邊的差值,因此圖中原本黑色區(qū)域的圖像由于與周邊差別很小,因此呈現(xiàn)高亮度;而在小型的矩形周圍隨著距離的增大,差別漸漸變小,因此亮度逐漸升高,無法體現(xiàn)原本黑色像素點處原本的亮度特性。
圖9.算法的測試圖(來自Retinex in Matlab)
從原始算法中可以看到,還有一個重要的步驟,就是迭代。迭代的作用是盡可能保留中央周邊差的分量,原本每次只保留中央周邊差的一半(見步驟4中最后的除2的處理),迭代次數(shù)越多,保留的分量就越多,迭代n次保留的分量就是,這樣局部的信息就更多,相當(dāng)于降低動態(tài)范圍的壓縮。這樣的操作可以使圖像更加自然,但是會增加運算量,下圖可以更加明顯地看出迭代次數(shù)的影響:
圖10.迭代次數(shù)的影響
為了方便各位自己研究,下面我給出該算法源碼供大家參考:
function Retinex = retinex_frankle_mccann(L, nIterations)% RETINEX_FRANKLE_McCANN: % Computes the raw Retinex output from an intensity image, based on the % original model described in: % Frankle, J. and McCann, J., "Method and Apparatus for Lightness Imaging" % US Patent #4,384,336, May 17, 1983 % % INPUT: L - logarithmic single-channel intensity image to be processed % nIterations - number of Retinex iterations % % OUTPUT: Retinex - raw Retinex output % % NOTES: - The input image is assumed to be logarithmic and in the range [0..1] % - To obtain the retinex "sensation" prediction, a look-up-table needs to % be applied to the raw retinex output % - For colour images, apply the algorithm individually for each channel % % AUTHORS: Florian Ciurea, Brian Funt and John McCann. % Code developed at Simon Fraser University. % % For information about the code see: Brian Funt, Florian Ciurea, and John McCann % "Retinex in Matlab," by Proceedings of the IS&T/SID Eighth Color Imaging % Conference: Color Science, Systems and Applications, 2000, pp 112-121. % % paper available online at http://www.cs.sfu.ca/~colour/publications/IST-2000/ % % Copyright 2000. Permission granted to use and copy the code for research and % educational purposes only. Sale of the code is not permitted. The code may be % redistributed so long as the original source and authors are cited.global RR IP OP NP Maximum RR = L; Maximum = max(L(:)); % maximum color value in the image [nrows, ncols] = size(L);shift = 2^(fix(log2(min(nrows, ncols)))-1); % initial shift OP = Maximum*ones(nrows, ncols); % initialize Old Productwhile (abs(shift) >= 1)for i = 1:nIterationsCompareWith(0, shift); % horizontal stepCompareWith(shift, 0); % vertical stependshift = -shift/2; % update the shift end Retinex = NP;function CompareWith(s_row, s_col) global RR IP OP NP Maximum IP = OP; if (s_row + s_col > 0)IP((s_row+1):end, (s_col+1):end) = OP(1:(end-s_row), 1:(end-s_col)) + ...RR((s_row+1):end, (s_col+1):end) - RR(1:(end-s_row), 1:(end-s_col)); elseIP(1:(end+s_row), 1:(end+s_col)) = OP((1-s_row):end, (1-s_col):end) + ...RR(1:(end+s_row),1:(end+s_col)) - RR((1-s_row):end, (1-s_col):end); end IP(IP > Maximum) = Maximum; % The Reset operation NP = (IP + OP)/2; % average with the previous Old Product OP = NP; % get ready for the next comparisonMcCann99 Retinex算法
McCann99 Retinex算法本質(zhì)上與McCann Retinex算法沒有區(qū)別,兩者不同的就是在McCann99算法中,不再是使用螺旋式的路徑來選取估計像素點,而是使用圖像金字塔的方式逐層選取像素。算法同樣經(jīng)取點、比較、平均這幾步進(jìn)行迭代運算。
圖像金字塔的概念很簡單,就是對圖像進(jìn)行下采樣,以多分辨率的形式表示圖像。最頂層的圖像分辨率最低,底層的最高(一般為原圖)。
圖11.圖像金字塔示意圖(來自網(wǎng)絡(luò))
如上圖所示,McCann99算法就是從頂層開始讓每一個像素點與其8個相鄰的像素進(jìn)行比較,估計反射率分量;前一層計算結(jié)束之后對估計的反射率分類進(jìn)行插值運算,使上一層估計的結(jié)果的圖像與金字塔下一層圖像尺寸相同,并再一次進(jìn)行相同的比較運算;最終,對原始圖像進(jìn)行8鄰域的比較結(jié)束后就能得到最終的結(jié)果,即增強(qiáng)后的圖像了。其中,比較操作與McCann算法相同,都是相減后求平均,見上一節(jié)步驟4中描述。
因此,McCann99算法,此處簡化描述為以下幾步:
1. 將原圖像變換到對數(shù)域,彩色圖像對各通道都進(jìn)行對數(shù)變換;
2. 初始化(計算圖像金字塔層數(shù);初始化常數(shù)圖像矩陣,該矩陣作為進(jìn)行迭代運算的初始值);
3. 從頂層開始,到最后一層進(jìn)行8鄰域比較運算,運算規(guī)則與MccCann Retinex算法相同,見上一節(jié)步驟4;
4. 第n層運算結(jié)束后對第n層的運算結(jié)果進(jìn)行插值,變成原來的兩倍,與n+1層大小相同(此處默認(rèn)n越大越靠近底層);
5. 當(dāng)最底層計算完畢得到的即最終增強(qiáng)后的圖像。
為了方便各位自己研究,下面我給出該算法源碼供大家參考:
function Retinex = retinex_mccann99(L, nIterations)global OPE RRE Maximum [nrows ncols] = size(L); % get size of the input image ; % compute the number of pyramid layers 2; % size of image to process for layer 0 2; 25not25error('invalid image size.') % at first layer end Maximum = max(L(:)); % maximum color value in the image ; % initialize Old Product 0:nLayersRR = ImageDownResolution(L, 2; % reduce input to required layer sizeOPE = [zeros(nrows,11; % pad OP with additional columns 12; OPE; zeros(1,ncols+2)]; % and rows 1; % pad RR with additional columns 1; RRE; RRE(end,:)]; % and rowsfor iter = 1:nIterationsCompareWithNeighbor(-10; % North 11; % North-East 01; % East 11; % South-East 10; % South 11; % South-West 01; % West 11; % North-WestendNP = OPE(2121; 105; %%% these two lines are equivalent with 105; %%% OP = imresize(NP, 2) if using Image 2; ncols = 2*ncols; % Processing Toolbox in MATLAB end Retinex = NP;function CompareWithNeighbor(dif_row, dif_col) global OPE RRE Maximum% Ratio-Product operation IP = OPE(2dif_row:12dif_col:1+dif_col)) + ...RRE(21212dif_row:12dif_col:1;IP(IP > Maximum) = Maximum; % The Reset step% ignore the results obtained inor columns for which the neighbors are undefined if (dif_col == -11212; end 1211; end 11221; end 1121; end 21212; % The Averaging operation 2121;function Layers = ComputeLayers(nrows, ncols) power = 2; % start from the Greatest Common Divisor 100)))power = power/2; % and find the greatest common divisor 2 Layers = log2(power);function Result = ImageDownResolution(A, blocksize) [rows, cols] = size(A); % the input matrix A is viewed as ; % a series of square blocks ; % of size = blocksize ; 1:result_rows % then each pixel is computed asfor crt_col = 1:result_cols % the average of each such blockResult(crt_row, crt_col) = mean2(A(11blocksize:crt_row*blocksize, ...11blocksize:;end en總結(jié)
????? 在上述兩個經(jīng)典的估計算法之后經(jīng)過反對數(shù)變換就可以恢復(fù)成原格式的圖像。通過試驗可以發(fā)現(xiàn),這些算法都還是有一定缺陷的,對于照度的估計后續(xù)還有很多算法如:單尺度Retinex (SSR)、多尺度Retinex (MSR)、可變框架的Retinex等等;還有針對增強(qiáng)后的光暈現(xiàn)象先用進(jìn)行照度分割,然后在再計算等等方法,本質(zhì)上都大同小異。這些改進(jìn)算法這里不再進(jìn)行介紹,有興趣的朋友可以去下載些論文看看。有不明白的或者本文有錯誤的地方也希望各位能夠指出,以免誤導(dǎo)后面的讀者。
歡迎關(guān)注公眾號:算法工程師的學(xué)習(xí)日志
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的matlab Retinex图像增强算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow2版本学习教程1-m
- 下一篇: matlab RBF 神经网络拟合