头像
mawen1250
核心会员
核心会员
帖子: 670
注册时间: 2011-07-24 20:33

gamma的概念及它给图像处理带来的相关问题

以下为我对gamma相关问题的理解,如果有不当之处欢迎指出。


图片
几种gamma标准(transfer characteristic)的曲线,横轴为Y/RGB的信号大小,纵轴为亮度。
图片
gamma=2.2的近似公式(纯幂函数关系)
图片
srgb标准的公式(部分线性,部分幂函数关系)
signal就是指gamma compressed的Y/RGB的量化值对应的信号值(0-1),power则是指linear scale的亮度值(0-1)

sRGB、SMPTE 170M(BT.709、BT.601)、SMPTE 240M、BT.2020的gamma compress与linear scale转换公式:

代码: 全选

#        sRGB        SMPTE 170M  SMPTE 240M  BT-2020
k0     = 0.04045     0.081       0.0912      0.08145
phi    = 12.92       4.5         4.0         4.5    
alpha  = 0.055       0.099       0.1115      0.0993 
gamma  = 2.4         2.22222     2.22222     2.22222

# gamma to linear
power  = (signal <= k0)       ? (signal / phi) : ((signal + alpha) / (1 + alpha)) ^ gamma

# linear to gamma
signal = (power  <= k0 / phi) ? (power  * phi) : (power ^ (1 / gamma)) * (1 + alpha) - alpha
1.Y/RGB的量化值0-255/16-235(8bit scale)与对应的亮度并不是线性的关系(linear scale),而是有一个基于gamma值的近似幂函数关系(指数通常为1.8、2.2-2.4,具体的标准可以参见H.264/H.265等文档,以及上方的公式),这种关系我们称之为gamma compression,在工业标准里称为transfer characteristic。注意YUV进行gamma compress的话只有作为亮度信号的Y受影响,UV作为色差信号是没有gamma这种概念的,但gamma compressed RGB和linear RGB分别转成YUV,这两者的UV实际上是不一样的——这点影响到之后讲的gamma-aware处理。

2.gamma这个东西产生的源头是在摄像端/CG渲染端,这些源端一般就已经将得到的图像量化值进行gamma compress了。最终输出端是显示设备,而一般的显示设备也有它的gamma特性。如果要获得正确的色彩还原,那么就必须让显示端和源端的gamma特性一致(实际上中间处理过程也是一样,下面就详细说明)。

3.由于量化值本身非线性的属性(gamma compressed),而一般的处理都是以量化值为linear scale的基础考虑的。如果做的处理没有考虑画面的gamma,而这个处理从原则上是针对亮度而非纯像素值的,这个处理就会导致画面对比度、亮度的失真。要实现gamma-aware的处理,需要将其转为线性的量化值(linear scale)然后再应用一般的处理。

4.对于gamma-aware处理与linear处理结果的区别,下面给一个直观的例子。
在srgb的gamma、PC Range下,像素值0(亮度0)和像素值255(亮度1)如果在线性下取平均,得到的像素值是128(亮度0.216),前后的亮度是有明显失真的,gamma-aware的平均后得到的像素值是188(亮度0.503),这样得到的前后亮度是一致的。188/255对应的是0.5亮度的中灰——这个例子也让我们对gamma compressed的概念有了更直观的理解。
这种失真的大小在进行计算的两个Y/RGB值的差距越大时也越明显,对应于resize/convolution这类spatial处理中,在局部高对比度区域影响会更明显(edge部分),下面的参考文章中的例子基本都是基于这个原理来设计的。
也就是说,我们通常所认为的0.25+0.75=1的概念是在线性空间下成立的,但是在像gamma compressed这种非线性空间下,线性的运算规律都会失效。用2作为gamma值的近似的话就和几何中用到的勾股定理的运算法则相同:0.25^2+0.75^2=0.79^2。
当然在现在图像领域使用的transfer characteristic标准中,也就是上方的公式里,是对亮度低于k0的部分使用线性压缩,高于k0的部分使用幂函数进行压缩。
而我们正确处理非线性空间(称之为gamma-aware的处理)的最简单办法就是先将其转成线性空间(linear scale)进行线性处理(linear处理),然后再将其转回非线性空间(gamma compressed),而不考虑gamma的影响直接对非线性空间进行线性处理我们称之为gamma-ignorant的处理。

5.但我们需要知道一点,之所以有gamma compression这种技术,在最早的模拟信号时代,是因为录制设备/回放设备本身的物理特性所致,输入输出的亮度和电压之间呈现的就是这种非线性关系(学过中学物理中的电学就应该知道P=U^2/R,而这里所说的设备的光电转换部分虽然不是简单固定的电阻R,但也是类似的道理),而其实人眼对光的亮暗呈现的也是非线性关系。这些物理特性导致了gamma这种概念的产生,而不同设备的物理特性之间的差别也导致了有多种gamma标准。
而到了数字信号时代,gamma仍然存在,它的重要意义之一就是在8bit-12bit这些低精度的图像色深下,给较暗的部分分配更大的量化区间(每2个相邻值之间的亮度差距小),相应地给较亮的部分分配较少的量化区间(每2个相邻值之间的亮度差距大),而这是符合人眼的视觉特性的(对暗部的亮度变化比亮部敏感)。我们经常说视频里的暗场有什么什么问题,实际上gamma compression在数字信号时代就是为了更好地保留暗场信息而存在的,现在人们有能力做出“电压——亮度”呈线性关系的显示器,但是大部分显示器仍然在沿用gamma这一概念。
所以如果我们要将8bit gamma compress的源转换为linear scale的图像,至少需要16bit来保留,实际上最好是有32bit float的精度来保留信息,根据我在AVS里的测试,8bit gamma->16bit linear->8bit gamma的转换都不是无损的,即使是16bit的中间精度还是会有rounding error。

6.大部分滤镜的处理过程都是gamma-ignorant的,只有少数如VariableBlur、ResampleHQ可以进行gamma-aware的处理(内部精度32bit float)。
dither工具中有下面的方法进行16bit下的gamma-aware处理。
先将输入的gamma compressed的图像转为16bit YUV/RGB48Y(应该根据源端是在YUV还是RGB下进行gamma compress来选择,但是通常来说gamma compress都是在RGB上进行的所以最好是用RGB48Y进行gamma-aware处理)。
通过Dither_y_gamma_to_linear将其按源端的transfer characteristic标准转为16bit linear scale。
做全程精度不低于16bit的处理,这个中间不能有降到8bit的过程(如nnedi3_resize16的upscale、GSMC、SMDegrain),根据上面第3条原因已经很明确了。
通过Dither_y_linear_to_gamma将其按显示端的transfer characteristic标准转为16bit gamma compressed。
例如对BT.709 transfer characteristic标准的输入源做gamma-aware的resize,输出给sRGB transfer characteristic标准的显示设备——这里同时也就做了一个transfer characteristic标准的转换:
# stacked-16bit input
Dither_y_gamma_to_linear(curve="709")
Dither_resize16(1280, 720)
Dither_y_linear_to_gamma(curve="srgb")
# stacked-16bit output
在播放环境中,我所知道的就是madVR支持gamma-aware的resize,madVR对于YUV420输入源的处理步骤如下:
按照设置的方式做chroma upscaling成为YUV444,根据源的matrix转换为gamma-compressed RGB,根据源的transfer characteristic转换为linear RGB,根据设置的方式做image upscaling/downscaling,根据显示器的transfer characteristic转换为gamma-compressed RGB,dither为8bit的RGB32输出给系统/DirectX接口,最后一步加入的gamma compress是根据你自己显示设备的设置进行的。
如果要让madVR做gamma-aware的resize,那么就要勾上image upscaling/downscaling里的scale in linear light,默认的不勾则是为gamma-ignorant的resize。
从实际效果来看,推荐对image downscaling使用gamma-aware的resize,而image upscaling时用gamma-aware resize会有比较明显的aliasing和ringing,所以不建议使用。

7.这里也能看出几个问题,例如压片时我们往往不知道视频原始的制作流程是怎样的——源端是在RGB还是YUV下采用何种transfer characteristic标准进行gamma compress的?
(考虑到实际摄制/渲染中一般都是生成RGB而gamma compression在这时就引入了,所以从正确性角度考虑gamma-aware的处理一般也应该在RGB下做)
而显示端的transfer characteristic标准又是一个不确定的东西,如果压片只是压给自己的可以按照自己用的显示设备来决定使用的transfer characteristic标准,如果压片是发出去的,那么又要怎么办?
所以如果光就压片中resize这一环节而言,最好的做法就是不要resize——as is——源是什么分辨率就保留什么分辨率。而且就从信息保留的角度而言,1080p源压制的高码720p往往是不如同码率的1080p(一个是又resizer滤除所有高频信息后再给Video Encoder决定保留什么信息,另一个是又Video Encoder决定保留什么信息舍去什么信息),当然这不是这篇文章的主题所以就不继续扯了。。。
当然由于几种常见的transfer characteristic标准的曲线都很接近(srgb相差稍微大一点),在源端和显示端都不确定的情况下,可以像下面那样做transfer characteristic标准近似的gamma-aware处理,前后的transfer curve相同所以不会发生transfer characteristic标准的转换。可以这样近似也是因为,相比于gamma-ignorant处理和gamma-aware处理之间的区别,不同transfer characteristic标准之间的区别可以说是小得多了。
# stacked-16bit input
Dither_y_gamma_to_linear(curve="709")
Dither_resize16(1280, 720)
Dither_y_linear_to_gamma(curve="709")
# stacked-16bit output
更具体的例子:
1920x1080 YUV420P8的输入源,按BT.709的Matrix和Transfer Curve将其转为Linear RGB48Y,downscale到1280x720,再按BT.709的Transfer Curve输出interleaved-YUV444P10。
# 1920x1080 TV-Range YUV420P8 input
Dither_convert_yuv_to_rgb(matrix="709", tv_range=True, lsb_in=False, output="rgb48y")
# Convert to RGB48Y with BT.709 matrix
Dither_y_gamma_to_linear(False, False, "709")
# Convert to linear RGB48Y with BT.709 transfer
Dither_resize16(1280, 720, Y=3, U=1, V=1)
# Linear resize to 1280x720
Dither_y_linear_to_gamma(False, False, "709")
# Convert to gamma compressed RGB48Y with BT.709 transfer

Dither_convert_rgb_to_yuv(SelectEvery(3, 0), SelectEvery(3, 1), SelectEvery(3, 2), matrix="709", tv_range=False, lsb=True, output="yv24")
# Convert to PC-Range stacked-YUV444P16
Down10(10, TVrange=False, stack=False)
# PC-Range interleaved-YUV444P10 output
1920x1080 YUV420P8的输入源,按BT.709的Matrix和Transfer Curve将其转为Linear RGB48Y,downscale到1280x720,再按sRGB的Transfer Curve输出RGB48Y/RGB24。
# 1920x1080 TV-Range YUV420P8 input
Dither_convert_yuv_to_rgb(matrix="709", tv_range=True, lsb_in=False, output="rgb48y")
# Convert to RGB48Y with BT.709 matrix
Dither_y_gamma_to_linear(False, False, "709")
# Convert to linear RGB48Y with BT.709 transfer
Dither_resize16(1280, 720, Y=3, U=1, V=1)
# Linear resize to 1280x720
Dither_y_linear_to_gamma(False, False, "srgb")
# Convert to gamma compressed RGB48Y with sRGB transfer

Down10(8, TVrange=False)
# Dither down to RGB24Y
MergeRGB(SelectEvery(3, 0), SelectEvery(3, 1), SelectEvery(3, 2))
# PC-Range RGB24 output
1920x1080 RGB24的输入源,按sRGB的Transfer Curve将其转为Linear RGB48Y,downscale到1280x720,再按sRGB的Transfer Curve输出RGB48Y/RGB24。
# 1920x1080 PC-Range RGB24 input
Interleave(ShowRed("Y8"), ShowGreen("Y8"), ShowBlue("Y8")).U16(TVrange=False)
# Convert to RGB48Y
Dither_y_gamma_to_linear(False, False, "srgb")
# Convert to linear RGB48Y with sRGB transfer
Dither_resize16(1280, 720, Y=3, U=1, V=1)
# Linear resize to 1280x720
Dither_y_linear_to_gamma(False, False, "srgb")
# Convert to gamma compressed RGB48Y with sRGB transfer

Down10(8, TVrange=False)
# Dither down to RGB24Y
MergeRGB(SelectEvery(3, 0), SelectEvery(3, 1), SelectEvery(3, 2))
# PC-Range RGB24 output
8.Dither_y_gamma_to_linear和Dither_y_linear_to_gamma都是通过Dither_lut16实现的(具体见dither.avsi中的Dither_linear_and_gamma),所以如果中间处理过程也是Dither_lut16的话可以将3个lut的表达式合为一个表达式,这样可以实现更快速的处理,而且由于建立LUT时,表达式的计算都是float精度的,所以不会有前面提到的16bit linear产生rounding error的问题。
例如我在压The Amazing Spider Man时,这片原盘里的Y范围只有16-184左右,我将其转为RGB48Y(量化范围0-50273);利用一个Dither_lut16的表达式,将其先按照BT.709的标准(这个我只能靠猜,我并不知道原始制作流程是如何的)转为linear scale(亮度范围0-0.589),再将此时获得的亮度信号除以0.589将亮度范围标准化到0-1,然后按照BT.709的标准转回gamma compressed,最终输出的是量化范围为0-65535的RGB48Y;最后转成PC Range的YUV444P10进行压制。
像这样gamma-aware的亮度标准化,相比于直接对量化范围做线性的标准化,在实际画面对比中区别也非常明显,后者导致很多纹理细节看起来都变得不明显(对比度失真),而前者在处理前后整个画面的对比度看起来都没有什么变化。
LWLibavVideoSource("D:\The Amazing Spider-Man 2012 4K Remastered Blu-Ray 1080p AVC DTS-HD MA 5.1-HDWinG\BDMV\STREAM\00001.m2ts", threads=1)

Crop(0, 140, 0, -140)

nnedi3_resize16(matrix="709", tv_range=True, lsb_in=False, output="RGB48Y")

c_num = 1 # SMPTE 170M (BT.709/BT.601)

# sRGB SMPTE 170M SMPTE 240M BT-2020
k0 = Select (c_num, " 0.04045", " 0.081 ", " 0.0912 ", " 0.08145")
phi = Select (c_num, "12.92 ", " 4.5 ", " 4.0 ", " 4.5 ")
alpha = Select (c_num, " 0.055 ", " 0.099 ", " 0.1115 ", " 0.0993 ")
gamma = Select (c_num, " 2.4 ", " 2.22222", " 2.22222", " 2.22222")

expr = "x 65535 /"
g2l = expr + " " + k0 +" <= " + expr + " " + phi +" / " + expr + " " + alpha + " + 1 " + alpha + " + / " + gamma + " ^ ?"
expr = g2l + " 0.58909115751250729778767280605716 /"
l2g = expr + " " + k0 + " " + phi + " / <= " + expr + " " + phi + " * " + expr + " 1 " + gamma + " / ^ " + alpha + " 1 + * " + alpha + " - ?"
expr = l2g + " 65535 *"

Dither_lut16(expr, y=3, u=1, v=1)

Dither_convert_rgb_to_yuv(SelectEvery(3, 0), SelectEvery(3, 1), SelectEvery(3, 2), matrix="709", tv_range=False, lsb=True, output="YV24")

Down10(dither=-3, TVrange=False, stack=False)
关于gamma-aware resize的一些测试及说明,也可以参考这篇文章

ResampleHQ文档里的例子:
原图
图片
Avisynth resizers(gamma-ignorant)
图片
ResampleHQ(gamma-aware)
图片
可以看出gamma-ignorant的resize很明显导致了对比度、亮度上的失真
上次由 mawen1250 在 2015-06-22 10:15,总共编辑 10 次。
头像
tnti
帖子: 46
注册时间: 2011-12-06 22:52

Re: gamma的概念及它给图像处理带来的相关问题

你可以试试NTSC和PAL的伽马值是不是一样的 口胡
Transfer characteristic=显象管信号光特性传输特性
Colour Profile=颜色配置
dynamic range compression=动态范围压缩
dynamic range=动态范围
{:cat_7} 楼下的英文我什么都不知道

这节要是看不懂的小白可以略过 {:cat_15}
上次由 tnti 在 2013-10-23 2:05,总共编辑 3 次。
我觉得一般底片都太清晰,生活不是如此的,我不喜欢那种清晰度,我总试着模糊些。
概念都是正确的废话
sswroom
核心会员
核心会员
帖子: 31
注册时间: 2012-08-03 1:42

Re: gamma的概念及它给图像处理带来的相关问题

這裏所說的Gamma, 在大部分的文獻中的名字是「Transfer characteristic」, 是在圖像處理中的「Colour Profile」中的其中一個環節。
DVD(VOB/MPEG-2)/Blu-ray(H.264)內部也有標記影片的Transfer characteristic, 只要跟據這個標記的Transfer characteristic去處理, 便能得出正確的亮度。

Transfer characteristic常見的錯誤:
1 - 有不少程式出現PC Scale(0-255)和TV Scale(16-235), 實際上PC和TV用相同的Scale, 完全不用這樣處理。較舊的影片, 黑色的地方變成灰色, 原因不是PC/TV Scale錯誤, 實際原因主要是影片的Transfer characteristic是NTSC, NTSC定義了0.075的數值為黑色, 如果在不支援Transfer characteristic的播放器上看, 黑色便會變成灰色

2 - DVD(MPEG-2)上定義了預設Transfer characteristic為BT.709, 但實際上市面的DVD中, 沒有Transfer characteristic標示的影片均為sRGB, 不是規格上的BT.709。


另外:
1 - "gamma-aware resize"方面, 縮細時"gamma-aware resize"明顯較好, 但放大時與普通的Resizer分別不大。由於影片播放時, 一般是放大, 所以用普通的Resizer已經足夠, 因為普通的Resizer速度快很多。

2 - 市面上有個名詞叫作「Dynamic range compression」(在中階的攝錄機見到), 實際上是指將Transfer characteristic內暗色與其他顏色, 用不同算式表達, 用來提升計算出來的Dynamic range值, 即是sRGB/BT.709等

3 - 現時市面上常用見的Transfer characteristic有:
-BT.709 (Mid-grade camcoder)
-BT.1361 (Mid-grade camcoder)
-Gamma 2.2 (Adobe RGB)
-Gamma 1.8 (Mac)
-sRGB (Windows)
-Linear RGB (Video Production)
-SMPTE 240M (Old camcoder)
-Log100 (Hi-grade camcoder)
-Log10^(1/2) (Hi-grade camcoder)
-NTSC (Old camcoder)
头像
Billy Herrington
帖子: 83
注册时间: 2013-01-09 9:54

Re: gamma的概念及它给图像处理带来的相关问题

supplement
transfer.png
from T-REC-H.265-201304-I!!PDF
头像
mawen1250
核心会员
核心会员
帖子: 670
注册时间: 2011-07-24 20:33

Re: gamma的概念及它给图像处理带来的相关问题

sswroom 写了:這裏所說的Gamma, 在大部分的文獻中的名字是「Transfer characteristic」, 是在圖像處理中的「Colour Profile」中的其中一個環節。
DVD(VOB/MPEG-2)/Blu-ray(H.264)內部也有標記影片的Transfer characteristic, 只要跟據這個標記的Transfer characteristic去處理, 便能得出正確的亮度。

Transfer characteristic常見的錯誤:
1 - 有不少程式出現PC Scale(0-255)和TV Scale(16-235), 實際上PC和TV用相同的Scale, 完全不用這樣處理。較舊的影片, 黑色的地方變成灰色, 原因不是PC/TV Scale錯誤, 實際原因主要是影片的Transfer characteristic是NTSC, NTSC定義了0.075的數值為黑色, 如果在不支援Transfer characteristic的播放器上看, 黑色便會變成灰色

2 - DVD(MPEG-2)上定義了預設Transfer characteristic為BT.709, 但實際上市面的DVD中, 沒有Transfer characteristic標示的影片均為sRGB, 不是規格上的BT.709。


另外:
1 - "gamma-aware resize"方面, 縮細時"gamma-aware resize"明顯較好, 但放大時與普通的Resizer分別不大。由於影片播放時, 一般是放大, 所以用普通的Resizer已經足夠, 因為普通的Resizer速度快很多。

2 - 市面上有個名詞叫作「Dynamic range compression」(在中階的攝錄機見到), 實際上是指將Transfer characteristic內暗色與其他顏色, 用不同算式表達, 用來提升計算出來的Dynamic range值, 即是sRGB/BT.709等

3 - 現時市面上常用見的Transfer characteristic有:
-BT.709 (Mid-grade camcoder)
-BT.1361 (Mid-grade camcoder)
-Gamma 2.2 (Adobe RGB)
-Gamma 1.8 (Mac)
-sRGB (Windows)
-Linear RGB (Video Production)
-SMPTE 240M (Old camcoder)
-Log100 (Hi-grade camcoder)
-Log10^(1/2) (Hi-grade camcoder)
-NTSC (Old camcoder)
感谢补充,我原先也对这张图做过测试,downscale时区别确实很明显,但upscale时也是有较明显的区别。不过在upscale时,可能是由于在Linear colorspace下resize过程产生的ringing经过了gamma compression后被放大,所以gamma-aware resize产生的ringing看起来似乎也比gamma-ignorant的resize要增强了不少,大概要配合anti-ringing的resize方法才能让结果比较好。

但是在这个问题上似乎doom9上madVR相关设置的讨论里出现了相反的结果,那里给出的一种推荐设置是:
image upscaling使用Jinc+anti-ringing,不勾scale in linear light(gamma-aware)。
image downscaling使用Catmull-Rom+anti-ringing,勾上scale in linear light(gamma-ignorant)。
根据帖子上的解释,downscale时用gamma-ignorant的linear light resize较好,但是ringing较强,所以还要加上anti-ringing算法。
就这个问题,从我在madVR上拿zone plate测试的结果来看,downscale时的ringing基本不容易看出来,加上了anti-ringing算法只会带来明显的aliasing。至于是否进行gamma-aware resize的问题,可能和源有关(有些情况下可能gamma-ignorant的结果更讨好眼睛),但就我目前接触到的gamma测试相关的画面以及从理论的角度来看,我认为还是用gamma-aware resize进行downscale更好。
所以我在madVR设置里的image downscale没勾scale in linear light也没勾anti-ringing。
上次由 mawen1250 在 2013-11-11 1:00,总共编辑 1 次。
sswroom
核心会员
核心会员
帖子: 31
注册时间: 2012-08-03 1:42

Re: gamma的概念及它给图像处理带来的相关问题

看了一下ResampleHQ, 它沒有說明用甚麼方法進行YUV 4:2:0 -> YUV 4:4:4, 這個會影響計算出來的質素

我之前測試Resizer是用RGB的相片來測試:
1) 星空的相片, 用Gamma-ignorant的Resizer縮細的話, 星星會變得暗淡。用Gamma-aware的Resizer縮細, 星星依然同樣清楚。
2) 在Notepad內輸入數個文字(白底黑字), 然後Screen Capture後再縮細, 用Gamma-ignorant的Resizer縮細, 文字會明顯變得深色。用Gamma-aware的Resizer縮細, 文字的深淺色沒有大分別。
放大的時候, 很難用肉眼分出那個是Gamma-aware放大, 那個是Gamma-ignorant放大。比較PSNR值時, Lanczos Resizer (5-tap以下)是Gamma-ignorant較好, 6-tap或以上是Gamma-aware較好。

P.S. 我常用的相片Resizer是Gamma-aware Lanczos Resizer (14-tap)
P.S.2 我現時進行YUV 4:2:0 -> YUV 4:4:4時, 水平用Lanczos Resizer (3-tap), 垂直用平均埴。優化後的Lanczos Resizer比用平均值的還要快
头像
mawen1250
核心会员
核心会员
帖子: 670
注册时间: 2011-07-24 20:33

Re: gamma的概念及它给图像处理带来的相关问题

今天又做了一下测试发现之前的判断错误了……madVR里勾上scale in linear light才是进行gamma-aware的resize,这样上面的疑惑也都解决了,而且scale in linear light这个词本身的意思也就能说得通了……
另外对于zone plate的测试发现,gamma-aware的resize在upscale时不仅仅是更容易产生ringing,还会有比较明显的aliasing,所以从upscale时的artifacts问题来考虑gamma-ignorant的resize的确是更加合适。
sswroom
核心会员
核心会员
帖子: 31
注册时间: 2012-08-03 1:42

Re: gamma的概念及它给图像处理带来的相关问题

Ringing與aliasing的問題, 應該是關於Resizing Algorithm(Lanczos/Bi-cubic/Bi-linear等)的問題, 而不是Gamma-aware/Gamma-ignorant的問題。
還有, 我的測試的圖片, 有不少是遠離現實, 偏向理論方面, 例如這兩幅圖片(sRGB色空間的)。
附件
遠看時, 整張相片是同樣的灰色, 不是灰色代表顯示器調校不正確
遠看時, 整張相片是同樣的灰色, 不是灰色代表顯示器調校不正確
同心圓的圖片, 將圖片縮細, 也應該只在中央見到同心圓, 其他方不應見到圓形圖案
同心圓的圖片, 將圖片縮細, 也應該只在中央見到同心圓, 其他方不應見到圓形圖案
头像
mawen1250
核心会员
核心会员
帖子: 670
注册时间: 2011-07-24 20:33

Re: gamma的概念及它给图像处理带来的相关问题

就说aliasing的问题,倒应该说跟resize的kernel没有什么太大的关系。
把zone plate的图从gamma转换成linear后(或是当作linear,转成gamma),就发现它的线条看起来有锯齿了。应该是原本其中用于减少锯齿的那些中间像素在gamma-linear/linear-gamma的转换后,不同像素值之间的差值改变了,失去了原本anti-aliasing的效果。而后续无论是用Lanczos、Jinc还是nnedi3、eedi3进行upscale,最后转换回gamma依然能看出明显的锯齿。
我的猜想是sampling时的anti-aliasing应用在gamma/linear上时就只在那种transfer characteristic下有最好的效果,而transfer characteristic转换后会aa的效果会打折扣,在此时进行upsample就进一步导致这个aliasing被放大,从而之后无论转成哪种transfer characteristic都会有比较明显的aliasing。
所以最理想的情况是在图像生成、处理到最终显示阶段始终保持Linear scale,这样既能避免非线性空间处理的问题,也能避免这类因为转换导致AA效果下降的问题。

Source
0-1 Gamma-compressed(Source).png
0-1 Gamma-compressed(Source).png (226.84 KiB) 查看 45763 次
Source Converted to linear scale
0-2 Linear scale.png
0-2 Linear scale.png (428.65 KiB) 查看 45763 次
Source upscaled with Lanczos
2-1 upscale in Gamma-compressed with Lanczos.png
Linear scale upscaled with Lanczos
2-2 upscale in Linear scale with Lanczos.png
Linear scale upscaled with Lanczos, then converted back to gamma-compressed
2-3 Gamma-aware upscale with Lanczos.png
Source upscaled with nnedi3
3-1 upscale in Gamma-compressed with nnedi3.png
Linear scale upscaled with nnedi3
3-2 upscale in Linear scale with nnedi3.png
Linear scale upscaled with nnedi3, then converted back to gamma-compressed
3-3 Gamma-aware upscale with nnedi3.png
头像
feisty2
帖子: 274
注册时间: 2012-08-05 10:03

Re: gamma的概念及它给图像处理带来的相关问题

源图像首先转换为linear light然后lanczos放大2倍 转回gamma compressed 使用sigmoid curve的结果
a000000.png
没有完美解决问题 但是已经有了明显改善

回到 “理论讨论 / Theoratical discussion”