色调映射

色调映射

目录导航

Photographic 算法

在此算法中,主要分为两个步骤来改变场景中的亮度,第一个步骤为整个场景的亮度改变(global),就如同在拍摄景物的时候需要调整相机的曝光值;第2个步骤为局部区块的亮度改变(local),这个步骤使用到了局部加亮和加深(Dodging & Burning)的概念

步骤一 整个场景的亮度改变

首先,根据照片红、绿、蓝3个颜色可以计算出照片中每个像素的亮度,再来需要算出场景中的关键值(key value),在这里关键值可以代表一个场景整体来说是亮的还是暗的,如果照片是白天拍摄的,就可以说其关键值是高的,若是在晚上拍摄的,则关键值会较低。在这里我们可以假设关键值会与场景中亮度的对数平均值相关。我们以来估计场景的关键值。

: 一个极小值,避免在算黑色像素的时候会遇到的情况算出场景中的关键值后,我们要将此关键值重新调整到中间值,调整方法为

其中为调整后新的关键值。

调整完后,会发现此方法尚无法解决场景过亮的地方会超出所能显示的颜色范围的问题。所以下一步是要将亮度高的地方压缩。

其中场景中亮度最高的值。由上述式子可以发现亮度接近最大亮度的像素会被压缩成,而亮度较低的地方压缩倍数则较少,如此即可保留低对比区域的细节,并且将高亮度的区域压缩至合理范围。

步骤二 局部区块的亮度

在使用完simple operator后,对于动态范围很高的影像,可以发现有些景物的细节还是无法被保留,所以此算法又提出了第二个步骤- 局部加亮与加深(Dodging & Burning)的作法。此作法是参考早期冲洗相片时的一个常用技巧。早期在冲洗底片的时候,为了能让照片中的某些区域曝光高一点,有些区域低一点,所以使用加亮和加深(Dodging & Burning)的技巧,在冲洗照片的过程中,将一些照片中的区域用纸张或是木头遮挡住,来调整不同区域的亮暗,此作法可以提升原本暗处的亮度或是让过曝的地方能够变暗一点,以看清楚照片中的细节。通常加亮与加深是使用在一个被高对比度包围的影像区域上,所以此方法首先要先找到对于每个像素而言,不存在强烈对比的最大区域。找寻方法为,将两个不同变异数的高斯函数套在影像上,得出两个结果 和 代表了给定某一个像素下,以此像素为圆心,在一个半径内的亮度平均值,而计算所使用的高斯函数的变异数较大,所以得出的结果为在一个较大半径内的平均值算法如下:

并以函数来凭断套用这两个不同高斯后的差别。当所计算区域内的亮度变化很小的时候,的差异很小,也就很小;当所计算区域内的亮度有很明显差异的时候,通常也就是位于物体边界的时候,会很大。

其中代表scale,此步骤会重复多次在不同的scale上,每次都会选用更大的变异数值。从最小的scale开始找起,目标是要找到最接近临界值,但是又小于临界值的scale。

最后的亮度可以表示为

其中为满足小于临界值下的。值得注意的是,在使用此算法的时候,如果选择的scale太大,也就是说每次变异数都变化很大的话或是临界值选择太大,都有可能会造成无法选择到正确的亮度无变化的最大区域,导致算法估计错误,最后影像会有明显黑边。

实作Photographic 算法

以下为使用Matlab所实作的Photographic 算法之程式码

1 function rgb = tonemap_p( hdr ) 2 //步驟1,調整整個場景的亮度 3 a = 0.6;//關鍵值設定 4 epsilon = 0.05; 5 6 //利用rgb計算照片亮度 7 lum_w = 0.27 * hdr(:,:,1) + 0.67 * hdr(:,:,2) + 0.06 * hdr(:,:,3); 8 image_size = size( hdr ); 9 [height, width] = size(image_size); 10 11 //計算L_w_bar(x,y) 12 sum_all = 0; 13 for i = 1: height 14 for j = 1: width 15 sum_all = sum_all + log( 0.00000001+ lum_w(i, j) ); 16 end 17 end 18 lum_white = 1e20; 19 lum_w_bar = double( exp (sum_all / N) ); 20 21 //計算L_d(x,y) 22 lum = a / lum_w_bar * lum_w; 23 for i = 1: height 24 for j = 1: width 25 lum_d(i, j) = lum(i, j) * ( 1 + lum(i, j) / lum_white / lum_white ) / (1 + lum(i, j) ); 26 end 27 end 28 29 //步驟二:加亮與加深(Dodging & Burning) 30 phi = 8; 31 //計算兩個不同變異數大小的高斯函數 32 for i = 1: height 33 for j = 1: width 34 for k = 1: 8 35 s = 1 * 1.6 ^ k; 36 alpha1 = 0.35; 37 R1(i, j, k) = exp( -( i ^ 2 + j ^ 2) / ( alpha1 ) ^ 2 ) / ( pi * ( alpha1 * s ) ^ 2 ); 38 alpha2 = 0.35 * 1.6; 39 R2(i, j, k) = exp( -( i ^ 2 + j ^ 2) / ( alpha2 ) ^ 2 ) / ( pi * ( alpha2 * s ) ^ 2 ); 40 end 41 end 42 end 43 //將亮度與高斯函數做卷積 44 for k = 1: 8 45 V1(:,:,k) = conv2( lum_w, R1(:,:,k)); 46 V2(:,:,k) = conv2( lum_w, R2(:,:,k)); 47 end 48 49 //計算函數V(x, y, s) 50 for i = 1: height 51 for j = 1: width 52 for k = 1:8 53 V(i, j, k) = ( V1(i, j, k) - V2(i, j, k)) / (2 ^ phi * a / (k ^ 2) + V1(i, j, k)); 54 end 55 end 56 end 57 58 //找尋符合V小於臨界值epsilon的scale 59 for i = 1: height 60 for j = 1: width 61 for k = 1:8 62 if abs(V(i, j, k)) < epsilon 63 V1_new(i, j) = V(i, j, k); 64 end 65 end 66 end 67 end 68 69 //計算新的亮度 70 for i = 1: height 71 for j = 1: width 72 lum_d2(i, j) = lum_w(i, j) / (1 + V1_new(i, j)); 73 end 74 end 75 76 //將rgb影像轉到hsv的系統後,改變亮度大小,最後輸出成色調映射後的結果 77 hvs = rgb2hsv( hdr ); 78 hvs(:,:,3) = lum_d2; 79 rgb = hsv2rgb( hsv); 80 end

图库

新西兰惠灵顿 圣保罗教堂 大堂,从 1/20 秒到 30 秒的曝光的八幅照片

两幅四级曝光差别的照片组合在一起,然后动态范围进行压缩以在标准显示器上显示

高动态范围落日图像。Taken as an exposure bracket of three images 2 stops apart.

A nighttime picture of San Francisco taken from an 8th floor hotel room using 3 exposures bracketed two stops apart.

An evening picture of Colmar using 5 exposures.

相关百科
返回顶部
产品求购 求购