着上篇往下讲,与White Patch Retinex相同,Gray-World 也是恢复图像原色的算法,两种算法最核心的不同在于对光源强度的估计。
Gray World 算法基于一个假设The Gray World Assumption:on average, the world is gray.也就是说自然图像的像素颜色平均值为常值1/2(在颜色范围归一化在[0,1]的情况下)。
下面讲述该算法的具体数学推导过程。
算法:
(1)基本算法
下式是图像成像的数学表达,具体的含义在上篇文章Color Constancy 色彩恒常性(1)White Patch Retinex中有讲到,这里就不再重复。
依然假设像素的色彩和像素的亮度值成比例。
按照Gray World假设,对取平均,则有
且
式中E(R) = 1/2即是由Gray World假设得出,带入后得到:
依然假设E(G)=1,那么光源的强度可以估计为:
(1)
最终经过色彩恢复后的图像为:
(2)
(2)改进算法
上述的原始算法具有很大的局限性。若图像的颜色比较单一,那么就不再满足gray world假设。为解决这个问题,提出了一些改进的算法,其中的一种主要思路是,先对图像进行分割,然后求分割后每块图像的颜色均值,进而求出总的颜色均值。用数学可以表示为下式:
式中,nr为分割后区域的个数,a(Rj)为第j个区域的平均像素值。通过这种方法求得最终的ai带入式(1)中。
在这种思想下,提出了一种具体的算法,该算法求三个通道的直方图,然后将其量化为10类,那么最终可以将256*256*256中颜色量化为10*10*10=1000种颜色,书中将这1000种类描述为1000 buckets。(直观的理解就是把整幅图像画一个直方图,该直方图有1000个柱,也就是1000个bucket)。
最终的求ai的式子为:
式中,nnz为直方图中像素点个数非0的bucket的个数,nb为bucket的总个数(按照书中的意思,nb =1000,我的理解是nb = nnz),ci(j)为第j个bucket中像素的值。
同样的,将求得的ai带入式(1)中,然后带入式(2)求得恢复后的输出。
MATLAB代码:
代码(其中,para=0是原始的方法,para=1是改进后的方法):
[plain] view plain copy print ?
- function out = GrayWorld(in,para)%
- %%%% copyright: ofalling %%%%
- if( nargin < 2 )
- para = 0;
- end
- out = zeros(size(in));
- inDouble = double(in)/255;
- % % gamma correction
- gamma = 1/2.2;
- inDouble = inDouble.^(gamma);
- if ( para == 0)% 最原始的gray world算法
- for i = 1:3
- a(i) = mean(mean(inDouble(:,:,i)));
- f = 2;% f = 2/E(G),assume E(G)=1
- out(:,:,i) = inDouble(:,:,i)/(f*a(i));
- end
- elseif( para == 1)% 先使用直方图分割为1000块再计算光源强度
- inR = inDouble(:,:,1);
- inG = inDouble(:,:,2);
- inB = inDouble(:,:,3);
- nb = 0;
- for r = 1:10
- for g = 1:10
- for b = 1:10
- bucket = find((inR>0.1*(r-1))&(inR<0.1*r)&(inG>0.1*(g-1))&...
- (inG<0.1*g)&(inB>0.1*(b-1))&(inB<0.1*b));
- if (size(bucket)~=0 )
- nb = nb+1;
- bucketC(nb,:) = [0.1*r-0.05 0.1*g-0.05 0.1*b-0.05];
- end
- end
- end
- end
- for i =1:3
- a(i) = mean(bucketC(:,i));
- f = 2;% f = 2/E(G),assume E(G)=1
- out(:,:,i) = inDouble(:,:,i)/(f*a(i));
- end
- end
(1)原始算法结果
(2)改进算法结果
对比实验(1)和(2)的结果,发现改进后的算法明显比原始的算法效果好。且改进后的算法使用范围更广。