關(guān)于色相Hue調(diào)整的問(wèn)題

問(wèn)題說(shuō)明

http://bbs.chinaffmpeg.com/a.html
遇到一個(gè)用canvas對(duì)圖片進(jìn)行hue-rotate 90和用ffmpeg fiter處理hue顏色對(duì)不上的問(wèn)題。中間看到很多東西初嘹,分析過(guò)程簡(jiǎn)單記錄一下掖疮。
原始視頻第一幀:

origin-video.png

js canvas ctx.filter = 'hue-rotate(90deg)'
canvas.png

ffmpeg: ffmpeg -y -i http://bbs.chinaffmpeg.com/b.mp4 -filter_complex "hue=h=90" -vframes 1 ffmpeg.jpg
ffmpeg.jpg

分析過(guò)程和中間遇到的問(wèn)題

初步懷疑是canvas使用HSL奉呛,ffmpeg使用HSV仑荐,簡(jiǎn)單的colorspace差異導(dǎo)致的問(wèn)題,對(duì)比了一下HSV和HSL的顏色表吵冒,研究了一下覺(jué)得兩個(gè)都不是直接簡(jiǎn)單的使用了HSL或HSV色彩空間搏屑,而是HCL。

HSL and HSV wiki中說(shuō)明了HSL和HSV的區(qū)別免胃,hue都是指色相音五,相對(duì)于RGB2HSL和RGB2HSV有相同的轉(zhuǎn)換公示,s是飽和度羔沙,L和V是定義上和含義上區(qū)別的躺涝,之前在color space的學(xué)習(xí)中說(shuō)過(guò)這個(gè)問(wèn)題。兩個(gè)顏色空間的S和LV由RGB計(jì)算的表達(dá)公式不一樣扼雏。photoshop的拾色器使用HSV坚嗜,查看花的色相Hue大概在320-350之間。至于為什么ps picker選擇HSB空間诗充,大致是因?yàn)镠SB的表達(dá)能力更強(qiáng)苍蔬、更符合人對(duì)于拾色器的習(xí)慣,請(qǐng)看知乎的一個(gè)討論蝴蜓。對(duì)照wiki碟绑,正向旋轉(zhuǎn)90度可以看出來(lái)大概的色彩。

394px-HSL_color_solid_cylinder_alpha_lowgamma.png

394px-HSV_color_solid_cylinder_alpha_lowgamma.png

photoshop-color-wheel.png

600px-HSV-RGB-comparison.svg.png

HSL&HSV&RGB.png

由于canvas不知道怎么實(shí)現(xiàn)的茎匠,從上面的wiki中發(fā)現(xiàn)問(wèn)題圖片中間的花紅色(320-340 degree之間)格仲,調(diào)整90度hue(50-70),應(yīng)該大致是黃色诵冒,跟canvas和ffmpeg的結(jié)果都對(duì)不上凯肋,相差有些大,到這里就覺(jué)得有些奇怪了汽馋。
先試了一下使用PS調(diào)整Hue否过,ps調(diào)整hue的功能跟picker不一致,我猜測(cè)使用的是HSL惭蟋,因?yàn)長(zhǎng)調(diào)整的時(shí)候是從黑到白的苗桂,而不是由最淺到最深,有的人說(shuō)是ps這里的調(diào)整L是帶著S一起調(diào)節(jié)的告组,還有一個(gè)stack overflow問(wèn)題煤伟,也有直接說(shuō)是用的HSL空間,我個(gè)人更傾向于HSL。調(diào)整90度以后得到的圖為:
photoshop-90.jpg

還有一個(gè)很常用的圖像處理開(kāi)源項(xiàng)目IM(ImageMagick后面簡(jiǎn)稱IM)有個(gè) modulate接口默認(rèn)使用HSL顏色空間便锨,很慶幸文檔中恰好給了一個(gè)紅花的示例圖片围辙,雖然并不是一樣的紅色。IM支持自己選擇顏色空間放案,比如HSL姚建、HSV等。上面的modulate命令默認(rèn)在HSL空間中hue調(diào)整90度吱殉,得到的結(jié)果是

convert ffmpeg-origin.png -modulate 100,100,150 ffmpeg-hsl-150.png

ffmpeg-hsl-150.png

使用HSB空間調(diào)整90度Hue:

convert ffmpeg-origin.png -define modulate:colorspace=HSB -modulate 100,100,150 ffmpeg-hsv-150.png

ffmpeg-hsv-150.png

HSB和HSL對(duì)于hue的定義是一樣的掸冤,看wiki中RGB->Hue的計(jì)算公式也一致,紅色的花朵變成了黃色友雳,跟顏色空間模型和PS基本都能對(duì)應(yīng)上了稿湿。不過(guò)還是對(duì)不上ffmpeg和canvas。

HCL顏色空間

在wiki中有一章Disadvantages押赊,這里大致是說(shuō)最早HSL或者HSV的提出是基于RGB轉(zhuǎn)換過(guò)來(lái)的饺藤,計(jì)算起來(lái)方便高效,也就是說(shuō)從RGB cube的color model中硬生生算出來(lái)一個(gè)色相流礁、飽和度涕俗、亮度(明度),計(jì)算快速神帅,符合當(dāng)時(shí)硬件的能力再姑,但是實(shí)際上HSL和HSV都不太符合真正的人眼對(duì)于色相飽和度亮度的看法。由于基于RGB變形枕稀,給了一個(gè)HSL的值還需要知道對(duì)應(yīng)的RGB空間询刹,比如sRGB、bt601等萎坷,甚至gamma值凹联,這就很不方便了。而且在HSL和HSV中的亮度都不太符合人眼所認(rèn)為的亮度哆档。

各種稱為亮度的空間對(duì)比

另外蔽挠,這倆空間都有些毛病,尤其是HSV的V和HSL的S瓜浸,比如在HSV中澳淑,純藍(lán)色和純白色有相同的value,在人眼看來(lái)純藍(lán)色明顯有著更高的亮度插佛,HSL中接近白色和純綠色有相同的S杠巡,而人眼看來(lái)純綠色明顯飽和度要高。另外雇寇,在做色相調(diào)整的時(shí)候氢拥,還會(huì)影響到人眼中認(rèn)為的SL/V蚌铜。既然這么多問(wèn)題,有些專家就說(shuō)那就拋棄HSB HSL好了嫩海,推薦用其他的球坐標(biāo)系LabLuv好了冬殃。

Luv和Lab都是后來(lái)在1976年提出的,都是直接基于XYZ的叁怪,不基于RGB spaces审葬,這樣就提供了視覺(jué)感知的一致性,而且兩個(gè)都有理論基礎(chǔ)奕谭,就是人眼的拮抗原理涣觉。像之前在color space的講解中說(shuō)的,Luv和Lab都是球坐標(biāo)系展箱,L都是希望是能表示人眼認(rèn)為的不變的亮度旨枯,uv和ab都是指顏色兩個(gè)方向上的“差異”蹬昌,uv或ab應(yīng)該都不是代表什么單詞的縮寫(xiě)混驰。更加類似于視頻處理的YUV中uv,這里借用知乎一篇回答jpg反復(fù)壓縮變綠的圖片皂贩,按照XYZ計(jì)算U的公式得到的結(jié)果栖榨,u更偏向于藍(lán)色的程度,v表示紅色的程度明刷,所以也可以認(rèn)為u是Cb分量婴栽,v是Cr分量。

yuv-uv.png

Luv極坐標(biāo)表示就是LCHuv辈末,這里L(fēng)不變愚争,將uv看作向量,兩個(gè)向量所表示的顏色的模為Chroma挤聘,夾角為Hue轰枝,用sRGB表示出來(lái)的色域圖如下:
SRGB_gamut_within_CIELCHuv.png

對(duì)應(yīng)的還有LCHab,基本原理是一樣的组去。ImageMagick支持很多種colorspaces鞍陨,恰好其中包括LCHuv和LCHab。使用LCHuv得到的結(jié)果:
IM-LCHuv-150.png

IM-LCHab-150.png

這里我們看到LCHuv得到的結(jié)果和ffmpeg基本一致从隆,但是還是不同诚撵。這里后面看源碼ffmpeg使用的就是LCHuv。LCHab的結(jié)果不同键闺,更接近c(diǎn)anvas得到的結(jié)果寿烟。

FFMPEG\IM\Canvas 實(shí)現(xiàn)

看看源碼實(shí)現(xiàn)吧。ffmpeg的源碼可以直接下到辛燥,我看的3.24筛武;canvas的firrefox和chrome都是開(kāi)源的盅藻,這里我看的是chrome源碼版本64.0.3253.1;ImageMagick源碼我看的是7.0.7-8

FFMPEG

FFmpeg中Hue調(diào)整代碼在libavfilter/vf_hue.c中畅铭,基本算法過(guò)程是:

1, compute_sin_and_cos (line:101)
   根據(jù)需要調(diào)整的HueContext計(jì)算Hue的sin cos氏淑,對(duì)于飽和度的調(diào)整根Hue一起,乘在sin和cos上
2硕噩,create_chrominance_lut (line:122)
   根據(jù)HueContext和計(jì)算出來(lái)sin cos計(jì)算出來(lái)一個(gè)顏色查找表hue_lut假残,這里ffmpeg為了速度并不是對(duì)每個(gè)pixel做Hue調(diào)整,而是對(duì)uv所有可能出現(xiàn)的值u[0-255]v[0-255]計(jì)算出來(lái)目標(biāo)值炉擅。這里consider U and V as the components of a 2D vector then its angle is the hue and the norm is the saturation辉懒,這樣就是一個(gè)初中幾何問(wèn)題了。    
   這里對(duì)照一下上面那個(gè)知乎上摳出來(lái)的uv圖就容易理解了谍失,從原點(diǎn)隨便一個(gè)vector眶俩,Saturation逐漸增大,Hue保持不變快鱼;確定半徑下旋轉(zhuǎn)一個(gè)vector颠印,是Saturation保持不變,Hue在逐漸調(diào)整抹竹。  
   uv旋轉(zhuǎn)以后的新坐標(biāo)是:  
   new_u = cos * u - sin * v;
   new_v = sin * u + cos * v;
3, 對(duì)AVFrame的成對(duì)的uv直接apply_lut(line:378)  
4线罕,對(duì)于亮度直接是y[0-255]計(jì)算出一個(gè)lut,然后對(duì)y pixels apply_lut

很高效的算法窃判,但ffmpeg的做法實(shí)際是有些問(wèn)題的钞楼,只是強(qiáng)把yuv的uv作為Hue調(diào)整的對(duì)象,沒(méi)有考慮color space和transfer袄琳,不過(guò)其實(shí)在Hue調(diào)整處理中询件,這些影響因素可能沒(méi)那么敏感了吧,對(duì)比IM的結(jié)果唆樊,ffmpeg得到的結(jié)果還有些跑偏宛琅。

ImageMagick

IM中調(diào)整Hue的代碼在enhance.c中,line:3092

static inline void ModulateLCHuv(const double percent_luma,
  const double percent_chroma,const double percent_hue,double *red,
  double *green,double *blue)
{
  double
    hue,
    luma,
    chroma;

  /*
    Increase or decrease color luma, chroma, or hue.
  */
  ConvertRGBToLCHuv(*red,*green,*blue,&luma,&chroma,&hue);
  luma*=0.01*percent_luma;
  chroma*=0.01*percent_chroma;
  hue+=fmod((percent_hue-100.0),200.0)/200.0;
  ConvertLCHuvToRGB(luma,chroma,hue,red,green,blue);
}

IM的算法還是比較標(biāo)準(zhǔn)的窗轩,對(duì)每個(gè)RGB pixel進(jìn)行處理(效率不高夯秃,但這不是重點(diǎn)),ConvertRGBToLCHuv在MagickCore/gem.c line:1375痢艺,先將RGB->XYZ仓洼,然后ConvertXYZToLuv,跟wiki公式一致堤舒,另外可以參考另外一篇關(guān)于HSV RGB等相互轉(zhuǎn)換的公式blog账千,這里使用圖片常見(jiàn)的sRGB茴她,得到LCHuv以后Hue執(zhí)行:

hue+=fmod((percent_hue-100.0),200.0)/200.0;

IM的Hue調(diào)整是百分比的方式

hue_angle = ( modulate_arg - 100 ) * 180/100 
modulate_arg = ( hue_angle * 100/180 ) + 100

最后轉(zhuǎn)換會(huì)RGB,perfect result查描!

Canvas hue-rotate

Canvas的執(zhí)行算法如上參考Chromium源碼render_surface_filters.cc line: 176撩银,或者另外一個(gè)地方FEColorMatrix.cpp。不過(guò)這里的轉(zhuǎn)換公式著實(shí)讓人懵逼:

chrome-hue.jpg

看一下計(jì)算S和Gray的GetSaturateMatrix和GetGrayscaleMatrix好像明白點(diǎn)什么,matrix的第一列就是RGB2XYZ的Y:

Y=0.2126729*r+0.7151522*g+0.0721750*b;

另外參考一本書(shū)InkScape中對(duì)于Saturation 的說(shuō)明能跟canvas的matrix對(duì)應(yīng)上,另外一本書(shū)Colour Reproduction in Electronic Imaging Systems中14.8.1小節(jié)好像也有些關(guān)系玻墅,而且Canvas變換Hue和Saturation的矩陣根SVG源碼中是一樣的,還有一個(gè)什么OpenPalace也都能對(duì)上壮虫,還有一個(gè)人統(tǒng)計(jì)了一堆css應(yīng)該使用的color轉(zhuǎn)換js……
雖然找到了很多一致的地方澳厢,但是大家好像都是抄的css源碼,并沒(méi)有什么“理論”的根據(jù)囚似。firefox line: 423源碼寫(xiě)的還算親民一些剩拢,至少知道了那一堆數(shù)字都是怎么來(lái)的!

firefox-hue.jpg

最終還是stack over flow的討論找到了答案饶唤。另一個(gè)stackOverFlow問(wèn)題中Michael Mullany的回答徐伐,css中的hue-rotate實(shí)現(xiàn)只是為了效率的線性近似,原始的HSL或HSV的計(jì)算非線性很復(fù)雜募狂,css做了一個(gè)線性近似办素,對(duì)于不是很純色的結(jié)果還算比較接近HSL:
less-pure-color-hue-HSLvsCSS.jpg

但是對(duì)于純色,CSS filter hue-rotate得到的結(jié)果在0-180度可以說(shuō)是很爛熬尺,在180-360還算可以摸屠。
Pure-color-hue-HSLvsCSS.jpg

如果想自己對(duì)比一下css結(jié)果和HSL)谓罗,Mullany給了一個(gè)對(duì)比css粱哼。

After all,css最終使用的近似方程是這樣子檩咱,想看證明的可以看一下MultiplyByZer0的回答

css-hue-rotate-equation.jpg

References

  1. HSL && HSV wiki
  2. Image magick document
  3. HSL && HSV color space disadvantages
  4. 知乎關(guān)于ps為什么選擇HSB作為拾色器
  5. LUV color space
  6. Lab color space
  7. jsfiddle net: A css online test
  8. color selector online tool
  9. Photoshop HSL HSP understanding
  10. A wikipedia pdf doc: HSL && HSV color space, and photoshop principle
  11. stack over flow, photoshop hue adjust
  12. 知乎討論 為何jpg反復(fù)壓縮質(zhì)量奇差且發(fā)綠
  13. chromium source code: render_surface_filter.cc
  14. 62.0.3178.1 chromium source code: render_surface_filter.cc
  15. HCL color space
  16. StackOverFlow: Why doesn't hue rotation by +180deg and -180deg yield the original color?
  17. StackOverFlow: How to transform black into any given color using only CSS filters
  18. Comparison of Hue Rotations: Red (S 50%, L 75%)
  19. w3.org hue rotate
  20. An interesting messages below 17 question
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揭措,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子刻蚯,更是在濱河造成了極大的恐慌绊含,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炊汹,死亡現(xiàn)場(chǎng)離奇詭異躬充,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)讨便,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)充甚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人霸褒,你說(shuō)我怎么就攤上這事伴找。” “怎么了废菱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵技矮,是天一觀的道長(zhǎng)抖誉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)衰倦,這世上最難降的妖魔是什么袒炉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮樊零,結(jié)果婚禮上梳杏,老公的妹妹穿的比我還像新娘。我一直安慰自己淹接,他們只是感情好十性,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著塑悼,像睡著了一般劲适。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厢蒜,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天霞势,我揣著相機(jī)與錄音,去河邊找鬼斑鸦。 笑死愕贡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巷屿。 我是一名探鬼主播固以,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嘱巾!你這毒婦竟也來(lái)了憨琳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤旬昭,失蹤者是張志新(化名)和其女友劉穎篙螟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體问拘,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遍略,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骤坐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绪杏。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖或油,靈堂內(nèi)的尸體忽然破棺而出寞忿,到底是詐尸還是另有隱情,我是刑警寧澤顶岸,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布腔彰,位于F島的核電站叫编,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏霹抛。R本人自食惡果不足惜搓逾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杯拐。 院中可真熱鬧霞篡,春花似錦、人聲如沸端逼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)顶滩。三九已至余掖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間礁鲁,已是汗流浹背盐欺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仅醇,地道東北人冗美。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像析二,于是被迫代替她去往敵國(guó)和親粉洼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容