Metal圖像處理——顏色查找表(Color Lookup Table)

前言

Metal入門教程總結(jié)
Metal圖像處理——直方圖均衡化
Metal視頻處理——綠幕視頻合成
本文介紹Metal下的顏色查找表(Color Lookup Table)撬槽。

正文

一張1024x1024的普通圖片,是由1024 * 1024=1048576個(gè)像素點(diǎn)組成厚骗,每個(gè)像素點(diǎn)包括RGBA共32bit椅寺,常見的圖像處理是對(duì)相鄰像素點(diǎn)顏色浑槽、像素點(diǎn)本身顏色做處理。
在對(duì)像素點(diǎn)本身顏色做處理的情況下返帕,需要把某個(gè)顏色映射成另外一個(gè)顏色桐玻,比如說(shuō)把顏色rgb(0.2, 0.3, 0.4) * colorMatrix = rgb(0.1, 0.2, 0.3),可以使用shader實(shí)現(xiàn)這個(gè)顏色轉(zhuǎn)變對(duì)圖片進(jìn)行處理荆萤。但實(shí)際過(guò)程中的顏色映射計(jì)算過(guò)程可能會(huì)更加復(fù)雜镊靴,并且會(huì)有很多冗余運(yùn)算(比如我們對(duì)相同的顏色會(huì)有重復(fù)的運(yùn)算),我們希望用空間換取時(shí)間链韭,把相同顏色值的運(yùn)算結(jié)果緩存下來(lái)偏竟。

如何避免冗余運(yùn)算?

假如我們用一個(gè)三維數(shù)組colorConvert來(lái)緩存這個(gè)結(jié)果敞峭,那么rgb(0.2, 0.3, 0.4) * colorMatrix處理就變成數(shù)組訪問(wèn)操作rgb(0.2, 0.3, 0.4) =colorConvert[0.2 * 255][0.3 * 255][0.4 * 255]=rgb(0.1, 0.2, 0.3)踊谋,運(yùn)算效率會(huì)有較高的提升。

但是數(shù)組長(zhǎng)度有512* 512 * 512= 134 217 728旋讹,太占用內(nèi)存殖蚕!我們可以減少數(shù)組每一維的大小轿衔,把512種可能減少為64種。同時(shí)為了有更好的過(guò)渡效果睦疫,每次計(jì)算的時(shí)候我們可以用相鄰的結(jié)果進(jìn)行線性結(jié)合呀枢。

我們以一維的情況為例,用數(shù)組a[64]來(lái)緩存512種顏色的映射結(jié)果笼痛。假如某個(gè)點(diǎn)的值是102,那么有102/4=25.5琅拌,映射結(jié)果為a[25] * 0.5+a[26] * 0.5缨伊,即兩邊各取一半;假如某個(gè)點(diǎn)的值是101进宝,那么有101/4=25.25刻坊,映射結(jié)果為a[25] * 0.25 + a[26] * 0.75,按照小數(shù)點(diǎn)進(jìn)行分配党晋。

這樣可以用合理的數(shù)組大小緩存運(yùn)算結(jié)果谭胚,并且可以在PC端提前計(jì)算出映射的數(shù)組。
接下來(lái)的問(wèn)題是:

如何把映射數(shù)組傳遞給shader未玻?

直接的方案是使用文本記錄映射結(jié)果灾而,然后把移動(dòng)端加載文本,讀取結(jié)果后存入內(nèi)存的數(shù)組buffer扳剿,再把buffer作為shader的一個(gè)參數(shù)旁趟。

這里我們肯定不采用這種辦法,而是采用顏色查找表(Color Lookup Table)庇绽。
我們的映射數(shù)組是colorConvert3[64][64][64]锡搜,相當(dāng)于64個(gè)二維數(shù)組colorConvert2[64][64]。如果我們colorConvert2[i][j]的結(jié)果寫入一張64 * 64的圖片第(i, j)個(gè)像素點(diǎn)瞧掺,即用一張64 * 64的圖片來(lái)緩存這個(gè)結(jié)果耕餐,如下:

對(duì)于colorConvert3[64][64][64],可以采用把64張圖片拼成一個(gè)8 * 8個(gè)小圖組成的大圖辟狈,如下:

最后肠缔,問(wèn)題只有:

如何從圖片讀取對(duì)應(yīng)運(yùn)算結(jié)果?

圖片有64個(gè)正方形上陕,每個(gè)小正方存著64 * 64的運(yùn)算結(jié)果桩砰。對(duì)于顏色rgb(x, y, z),我們先用z值算出正方形的位置释簿,再用(x亚隅,y)讀取對(duì)應(yīng)結(jié)果。
整個(gè)過(guò)程如下:(shader中的顏色值都是歸一化后的結(jié)果庶溶,區(qū)間為[0, 1])

  • 1煮纵、用藍(lán)色值計(jì)算正方形的位置懂鸵,得到quad1和quad2;
  • 2行疏、根據(jù)紅色值和綠色值計(jì)算對(duì)應(yīng)位置在整個(gè)紋理的坐標(biāo)匆光,得到texPos1和texPos2;
  • 3酿联、根據(jù)texPos1和texPos2讀取映射結(jié)果终息,再用藍(lán)色值的小數(shù)部分進(jìn)行mix操作;

整個(gè)shader如下:


constant float SquareSize = 63.0 / 512.0;
constant float stepSize = 0.0; //0.5 / 512.0;

fragment float4
samplingShader(RasterizerData input [[stage_in]], // stage_in表示這個(gè)數(shù)據(jù)來(lái)自光柵化贞让。(光柵化是頂點(diǎn)處理之后的步驟周崭,業(yè)務(wù)層無(wú)法修改)
               texture2d<float> normalTexture [[ texture(LYFragmentTextureIndexNormal) ]], // texture表明是紋理數(shù)據(jù),LYFragmentTextureIndexNormal是索引
               texture2d<float> lookupTableTexture [[ texture(LYFragmentTextureIndexLookupTable) ]]) // texture表明
{
    constexpr sampler textureSampler (mag_filter::linear,
                                      min_filter::linear); // sampler是采樣器
    float4 textureColor = normalTexture.sample(textureSampler, input.textureCoordinate); //正常的紋理顏色
    
    float blueColor = textureColor.b * 63.0; // 藍(lán)色部分[0, 63] 共64種
    
    float2 quad1; // 第一個(gè)正方形的位置, 假如blueColor=22.5喳张,則y=22/8=2续镇,x=22-8*2=6,即是第2行销部,第6個(gè)正方形摸航;(因?yàn)閥是縱坐標(biāo))
    quad1.y = floor(floor(blueColor) * 0.125);
    quad1.x = floor(blueColor) - (quad1.y * 8.0);
    
    float2 quad2; // 第二個(gè)正方形的位置,同上舅桩。注意x酱虎、y坐標(biāo)的計(jì)算,還有這里用int值也可以江咳,但是為了效率使用float
    quad2.y = floor(ceil(blueColor) * 0.125);
    quad2.x = ceil(blueColor) - (quad2.y * 8.0);
    
    float2 texPos1; // 計(jì)算顏色(r,b,g)在第一個(gè)正方形中對(duì)應(yīng)位置
    /*
     quad1是正方形的坐標(biāo)逢净,每個(gè)正方形占紋理大小的1/8,即是0.125歼指,所以quad1.x * 0.125是算出正方形的左下角x坐標(biāo)
     stepSize這里設(shè)置為0爹土,可以忽略;
     SquareSize是63/512踩身,一個(gè)正方形小格子在整個(gè)圖片的紋理寬度
     */
    
    texPos1.x = (quad1.x * 0.125) + stepSize + (SquareSize * textureColor.r);
    texPos1.y = (quad1.y * 0.125) + stepSize + (SquareSize * textureColor.g);
    
    float2 texPos2; // 同上
    texPos2.x = (quad2.x * 0.125) + stepSize + (SquareSize * textureColor.r);
    texPos2.y = (quad2.y * 0.125) + stepSize + (SquareSize * textureColor.g);
    
    float4 newColor1 = lookupTableTexture.sample(textureSampler, texPos1); // 正方形1的顏色值
    float4 newColor2 = lookupTableTexture.sample(textureSampler, texPos2); // 正方形2的顏色值
    
    float4 newColor = mix(newColor1, newColor2, fract(blueColor)); // 根據(jù)小數(shù)點(diǎn)的部分進(jìn)行mix
    return float4(newColor.rgb, textureColor.w); //不修改alpha值
}

總結(jié)

顏色轉(zhuǎn)換表是在網(wǎng)上找了一張胀茵,特此感謝——LUT(顏色查找表)的來(lái)源
Shader部分參考自GPUImageLookupFilter挟阻,demo的地址在這里琼娘。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市附鸽,隨后出現(xiàn)的幾起案子脱拼,更是在濱河造成了極大的恐慌,老刑警劉巖坷备,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熄浓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡省撑,警方通過(guò)查閱死者的電腦和手機(jī)赌蔑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門俯在,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人娃惯,你說(shuō)我怎么就攤上這事跷乐。” “怎么了趾浅?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵愕提,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我皿哨,道長(zhǎng)揪荣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任往史,我火速辦了婚禮,結(jié)果婚禮上佛舱,老公的妹妹穿的比我還像新娘椎例。我一直安慰自己,他們只是感情好请祖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布订歪。 她就那樣靜靜地躺著,像睡著了一般肆捕。 火紅的嫁衣襯著肌膚如雪刷晋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天慎陵,我揣著相機(jī)與錄音眼虱,去河邊找鬼。 笑死席纽,一個(gè)胖子當(dāng)著我的面吹牛捏悬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播润梯,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼过牙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了纺铭?” 一聲冷哼從身側(cè)響起寇钉,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舶赔,沒(méi)想到半個(gè)月后扫倡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顿痪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年镊辕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了油够。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡征懈,死狀恐怖石咬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卖哎,我是刑警寧澤鬼悠,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站亏娜,受9級(jí)特大地震影響焕窝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜维贺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一它掂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溯泣,春花似錦虐秋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至肢簿,卻和暖如春靶剑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背池充。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工桩引, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人收夸。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓阐污,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親咱圆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笛辟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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