头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

请教一些渲染器的问题(已解决)

前几天也写了程序算了下8bit RGB转YUV然后再转回8bit RGB,
和虽然有些小差异,但数据和这贴结果差不多
http://forum.doom9.org/showthread.php?t=164450

我是用
8bit-RGB—(truncate)—> 23bit-YCbCr —(rounding) —> 16bit-YCbCr—(rounding) —>10bit-YCbCr —(truncate) —> 23bit-RGB —(rounding)—> 8bit-RGB
公式用的是BT.601
把源8bit-RGB和转换后的8bit-RGB对比,100%没有损失

实际操作时
在avs里先用Dither_convert_rgb_to_yuv把8bit-RGB转到16bit-yv12
然后用f3kdb的Ordered dithering转到10bit的(没有找到可用的高精度rounding到10bit的函数)
这个转换带来的损失估计很小
(因为我不放大和源对比,没看出区别,放大400%也几乎没看出区别,
要证明有区别,就是同一画面源png截图大小是60KB,转换后截图是100KB),
这个损失也许是chroma upscaling/downscaling造成的(全程用的是Bicubic)
渲染器用的是不开dither的madVR

问题主要是渲染器方面
如果10bit-YCbCr转到8bit-RGB 这个过程精度不高,那么造成损失是必然的
想请问下一般的渲染器这个过程用的是查表法还是实时运算?
——————————————————————————————————————————————————————————————
如果是查表法的话,那么就不关运算精度的问题了,
但是我想查表法应该也只有8bit-YCbCr转到8bit-RGB的数据
没有10bit-YCbCr转8bit-RGB的
所以接受10bit-YCbCr数据时,右移两位成8bit,然后再通过查表法转到8bit RGB
这个过程损失是挺大的

——————————————————————————————————————————————————————————————
如果是实时运算的话,那么精度有多少呢?
如果运算时精度低,也会造成损失
madVR貌似是先左移位到16bit-YCbCr,
然后转成16bit-RGB,然后再通过dither或rounding到8bit RGB
如果是这样的话,是没什么损失的

但madVR的dither算法好像有点问题的样子
比如我打开一个8bit yv12视频,选了dither,
8bit yv12视频理应来说不会产生dither造成的杂点,
但实际上产生了
没用dither,颜色倒是正常

打开一个8bit-rgb转成10bit的yv12的视频,
没选dither,颜色正确
选了dither,产生了dither带来的杂点
————————————————————————————————————————————————————
我想表达的是
我这里用了madVR的dither

本来能还原成8bit RGB的YUV数据,没能还原,做了dither处理
不能够还原成8bit RGB的YUV数据,却被错误的当做能还原的数据,没有做dither

现在用10bit压制都是用的有损压缩吧,
那么当中有一部分数据是8bit RGB能表达的,有一部分是不能表达的
如果是8bit RGB能表达的颜色,进行了dither处理,
不能表达的颜色没有进行dither处理
那么用madVR渲染出来的视频颜色不就乱了?
————————————————————————————————————————————————————
感觉表达的好混乱
麻烦各位指点迷津,谢谢

avs里

代码: 全选

Dither_convert_rgb_to_yuv(lsb=true)
f3kdb(Y=0,Cb=0,Cr=0,grainY=0,grainC=0,sample_mode=1,input_mode=1,input_depth=16,output_mode=2,dither_algo=2,output_depth=10)
x264参数

代码: 全选

avs4x264mod -L"x264_64_tMod-10bit-all.exe" --input-depth 10 --qp 1 "FFV1.avs" --output "x264_10bit_i420.mp4"
pause
附件
test.rar
源和压制好的10bit视频
(379.06 KiB) 下载 77 次
上次由 zhongpang 在 2012-04-15 16:31,总共编辑 1 次。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 请教一些渲染器的问题

太混亂了看不懂…
没有找到可用的高精度rounding到10bit的函数
round到10bit不就是第11bit開始四捨五入麼,什麼叫高精度rounding到10bit的函數?
要证明有区别,就是同一画面源png截图大小是60KB,转换后截图是100KB),
这个损失也许是chroma upscaling/downscaling造成的(全程用的是Bicubic)
不是。ordered dithering本身會導致這個問題。相比之下8bit rgb->16bit yuv420->8bit rgb的損失幾乎可以忽略不計。
如果是查表法的话,那么就不关运算精度的问题了,
但是我想查表法应该也只有8bit-YCbCr转到8bit-RGB的数据
没有10bit-YCbCr转8bit-RGB的
所以接受10bit-YCbCr数据时,右移两位成8bit,然后再通过查表法转到8bit RGB
这个过程损失是挺大的
madVR默認是16-bit 3d-lut,當然是查表,不過不管源是8bit還是10bit,默認下都是在16bit精度下的lut,不可能是>>2然後8bit lut,否則madVR肯定是10bit播放環境裡最糟糕而不是最好的渲染器了。就像顯示器不會有內部lut處理精度比最終顯示精度還低的一樣,madVR也不會做這種腦殘的事情。
8bit yv12视频理应来说不会产生dither造成的杂点,
但实际上产生了
没用dither,颜色倒是正常
這麼說吧。yuv420的csp轉換到rgb,在不考慮lut而直接用matrix轉換的情況下,必然有float->int的過程,理論上不管是8bit還是10bit的源都存在,所以要想質量最好的話都需要dither。而madVR除非trade quality for performance,否則始終是16bit處理的,所以madVR在當初根本沒有非商用10bit編碼器的情況下默認就已經開dither了。

後面的完全看不懂是什麼意思了。想問個問題。樓主到底是做什麼處理的。如果是視頻處理的話,從yuv420的源開始全程YUV是比較正常的流程,中途不會涉及到RGB->YV12的過程,自然也沒這麼多奇怪的現象。請問究竟有什麼理由不可以全程YUV,而非要走RGB?

同樣這裡的“雜點”到底是指什麼我也無法確定。像Ordered dithering之類的算法一般會配合一定程度的noise,來降低產生的pattern感;同時ordered dithering還可以通過峰值差來調節dither的強度;而像error diffusion dithering的話,我更懷疑這所謂的雜點是指dithering過程通過增加對error的容量產生的增強dither的效果。“雜點”究竟是指這三個裡哪一種不得而知,但是只要是lsb不為0時做dither就一定會有,如果沒有的話感官上的效果一定比有更糟糕。

而且avs、x264、madVR全部都是針對視頻的工具,就算是RGB的輸入,在動態播放過程中也一般不會出現你說的明顯可見以至於會影響感官的雜點出現,相比之下對比單幀則更容易看出來。但是視頻本身就是動態播放的,如果是單幀能看出的問題而動態播放看不出來(譬如動態噪點明明播放時看不出來確非要單幀去看損失,譬如動態的dither pattern明明動態播放時看不出痕跡卻非要單幀去看pattern),對視頻處理來說就不是問題,對圖像處理來說才是問題。如果樓主是想對單幀的圖像來做處理,自然dither帶來的感官差會非常大,而在視頻動態播放時這種問題幾乎不可見。

樓主之前發的帖子裡,我都是通過dither_convert_rgb_to_yuv將RGB轉成16-bit yuv420,在avs裡全程16-bit處理,最後轉成10-bit的yuv420p10進行編碼,最後將編碼結果用hack版ffms吃入成yuv420p16,用Atkinson或者Floyd-steinberg轉回8bit yuv,然後才轉rgb截圖(最後我沒有直接從16bit轉成rgb,就是想連這個過程的損失也加進去看到底會有多大)。另一組方式是dither_convert_rgb_to_yuv將RGB轉成16-bit yuv420,在avs裡全程16-bit處理,最後轉成8-bit的yuv420進行編碼。用了較低的qp值來保證x264本身不會出現artefacts。實際上結果不管是10bit還是8bit的輸出,不管是avs內截圖還是madVR播放都沒有出現較大的損失。可見8-bit rgb->8-bit yuv/rgb在合適的處理下都可以做到感官上損失很小的結果。用10bit編碼對我來說純粹是利用高精度的高容錯能力來降低碼率,用高精度來容納更多的RGB數據確實是10bit的一項優勢,但是即使不利用這種優勢8bit rgb->8bit yuv也可以利用有限的色域還原效果不錯的結果。

既然是有損處理有損編碼,損失肯定有。如果樓主真的:
1. 不能接受任何損失,想讓輸入的RGB和播放時的RGB沒有區別
2. 必須用RGB的源,出於各種理由
3. 要求單幀級的感官效果
請不要轉YUV,直接用x264內的--output-csp rgb來進行編碼,qp盡量接近或者使用0。
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: 请教一些渲染器的问题

感谢taro大解释

我有一些源是8bit RGB的swf (http://115.com/file/anq2srqj),
但是由于banding很多(如果能让swf 10bit量化的话,可以避免放大产生的banding,不过貌似找不到方法的样子)

不得不先在AU里deband处理
在AU处理之后,转为无损 8bit RGB
也就是经过了8bit-RGB—>12bit YUV—>8bit RGB过程
除了滤镜带来的损失以外,没有其他损失,
也就是说可以看做是在源RGB的环境里处理的

得到的无损FFV1编码的文件很大,
故想要用x264有损压缩处理使文件体积变小
如果用8bit x264 rgb输出,
由于对源几乎全篇进行了deband处理,
而且全篇都是暗景,
而且fade场景也很多,
尽管x264里zone到手软,参数EP,码率15M也达不到理想效果(分辨率为1920x984)

于是尝试用10bit x264,
但10bit x264好像不支持rgb输出
于是只有转到yuv来处理

理论上来说8bit rgb转16bit yuv转10bit yuv然后转16bit RGB然后再转回8bit rgb
这个过程是无损的,如果都用rounding的话

现在遇到的问题是
我用压出来无损x264,播放出来并不是无损的
根据taro大的解释,是因为16bit yuv转10bit yuv用了dither的原因

我理解的dither是

8bit RGB(1,1,1)左移位到10bit是RGB(4,4,4)
10bit RGB(4,4,4),右移位到8bit是(1,1,1)
故10bit RGB(4,4,4)可以用8bit(1,1,1)来直接表示(虽然实际上颜色不一样)

10bit RGB(7,7,7)右移位到8bit也是(1,1,1),
但8bit RGB没有一个数据可以通过左移变成10bit(7,7,7)
故如果一副10bit的图全部像素都是RGB(7,7,7)的话,

如果truncate到8bit,应该是全部像素都是RGB(1,1,1)
如果rounding到8bit,应该是全部像素都是RGB(2,2,2)
用dither到8bit的话,应该整幅图有几种不同的颜色,
也就是说引入杂点(8bit各种颜色)让人眼看起来像是10bit RGB(7,7,7)

所以说如果我10bit的源是8bit左移得来的,
那么即使我使用了dither到8bit,也应该不会产生杂点,
这时dither也就相当于rounding
但实际上并不是这样

我想问的是
1.能不能在avs里16bit转10bit时能不能不用dither而用rounding?
我关闭dither貌似用的就是truncate了

2.在播放有损压制的10bit yv12时,使用dither带来的瑕疵不能很大
比如播放用8bit rgb无损压制的10bit yuv时,不产生dither带来的瑕疵
我想不通的是在madvr里如果开了dither的话
播放8bit的视频,按理来说根本就不需要dither,用rounding就可以了
但是还是使用了dither,
但在较暗平滑部分才比较明显,和rounding比起来,感觉脏了些
放大400%后看,有dither带来的杂点
所以纠结的是渲染器dither算法的问题
上次由 zhongpang 在 2012-04-15 10:10,总共编辑 1 次。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 请教一些渲染器的问题

1. Dither_lut16("x 32 + 6 >>"),或者直接Dither_lut16("x 64 /")。

2. rgb轉成yuv420p10然後無損編碼,此時yuv420p10的2bit LSB不為零,如果播放時渲染器輸出的是8bit RGB(譬如madVR),要么dither要么不dither。LSB不為零的情況下dither則必然和源數據有差異,round則容易出banding。
播放8bit的视频,按理来说根本就不需要dither,用rounding就可以了
YUV->RGB,如果是按matrix計算出來的值都是float,或者像madVR用3d-lut的話出來的值都是16-bit的,這裡不管是float還是16-bit integer,LSB都不是0,降到8bit integer想要質量肯定要dither,不需要質量的話才是round,不知道您說的不需要dither按的到底是什麼理…

話說現在看片都是用400%的比例麼…真可怕…
再說放大400%的過程本身就會產生artefacts,尤其是dither這種high frequency的數據在high pass的upscale這種filter面前不知道都變成啥樣子了…

於是順便拿640x640的zone plate來測試一下16bit下madVR用的resize算法的效果(4x interpolation,Spline64+SoftCubic75,ordered dithering):
[syntax lang="avisynth" lines="f"]ImageReader("E:\IDM_Download\z\AVS\Plugins\Resize\zoneplate-640x640.bmp")

w=width
h=height

Dither_Convert_RGB_TO_YUV(lsb=true)

Dither_resize16(w*4, h*4, kernel="Spline64", U=1, V=1).MergeChroma(
\ Dither_resize16(w*4, h*4, kernel="Bicubic", a1=0.75, a2=0.25, Y=1) )

Dither_Convert_YUV_TO_RGB(lsb_in=true, matrix="601")
[/syntax]
圖較大,所以就設成點擊打開了:
源:http://www.nmm-hd.org/upload/get~OOs2ml ... 40-opt.png
結果:http://www.nmm-hd.org/upload/get~zYRhqc ... 60-opt.png
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: 请教一些渲染器的问题

感谢taro大指点,现在明白了
原来是转换后lsb不为0,自己没考虑周全,闹笑话了 {:cat_5}

还想avs请教下是这样写吗?

Dither_convert_rgb_to_yuv(lsb=true)
Dither_lut16("x 64 \")
DOWN.C16

不知为什么压出来是黑屏
_______________________________________
原来Dither_lut16 输出也是16bit
还要再加个
Dither_lut16("x 6 <<")
不过这个貌似只让Y的lsb为0了,U,V上的好像还是没变的样子
——————————————————————————————
解决了
现在可以压出经过转换能无损的到源8bit RGB的10bit 的yv24了
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: 请教一些渲染器的问题(已解决)

付几张渲染器效果图

话说,
madvr渲染10bit yuv全采样的视频真耗资源,不就是多了1倍的数据么
420时,帧率是30fps,444时,帧率为个位数
VMR9等其他的倒是比较快

均为ffdshow解码
源是无损编码的x264 10bit 444
——————————————————————————————
源
madVR渲染 未开dither(相对于源无损)
madVR渲染 未开dither(相对于源无损)
madVR渲染 开启dither
madVR渲染 开启dither
VMR9渲染
VMR9渲染
——————————————————————————————


有损编码的x264 10bit 444
——————————————————————————————
源2
源2
madVR渲染 未开dither
madVR渲染 未开dither
madVR渲染 开启dither
madVR渲染 开启dither
VMR9渲染
VMR9渲染

回到 “理论讨论 / Theoratical discussion”