源碼可見:[直接點擊](Github的README會更新Change Log和待辦任務(wù)TODO,強烈建議關(guān)注)
1.背景
圖像提取主色調(diào)來增強浸入式交互體驗的場景越來越常見,如知乎網(wǎng)頁版的個人主頁,Instagram的圖片色調(diào)篩選。那如何去獲得一張照片的主色調(diào)呢?Google在Android.support.v7里,給出了一個叫做Palette(調(diào)色板)的方案。它的效果如下:

關(guān)于這套算法,我已經(jīng)在之前的文章中給出了解析(點擊查看)。算法雖好,可是它卻是用Java寫的,而且用了很多Android或者Java很多工具庫的類。我們iOS黨跟Palette之間可謂是程序員之間最遠的距離:“你的源碼就在那里不離不棄,我卻望著不能調(diào)用的API徒增嘆息”。
不過現(xiàn)在,咱們iOS黨也有自己的Palette了!讓我們調(diào)著Objective-C的API,趁著2017年WWDC的改革東風(fēng),走上通往幸福的康莊大道!
2.為什么要用Palette?
有人是否要問了,不就是提取圖片主色調(diào)嘛,我遍歷一遍圖片的所有像素信息,然后統(tǒng)計一下哪個RGB值最多,不就是主色調(diào)嘛?
這種方案可不可以?并不是不可以,在一些簡單的場景中,這樣算的出來的效果也能差強人意。但是考慮一下這些場景:淘寶上的一張帶有深色背景的商品圖,夜晚的霓虹燈,如:

一排排黃的出油的ofo擺在灰色的大地上:

又或者當(dāng)圖片的主色調(diào)并不是純色,而是處于漸變狀態(tài),這樣就會分散RGB值,出現(xiàn)較大誤差。所以我們很容易發(fā)現(xiàn),圖片的主色調(diào)往往并不是單純的出現(xiàn)次數(shù)最多的RGB值。它應(yīng)該符合我們?nèi)搜鄣牧?xí)慣,是我們一眼就能辨識出來的視覺焦點。而這正是Palette真正厲害之處。
3.所以Palette做了什么?
Palette有兩大特色,也分別解決了兩個大問題,一是解決提取顏色是否是視覺焦點的問題,二是顏色分散的問題。
(1)怎么解決顏色視覺焦點問題?
RGB色彩模式描述了三種顏色通道,這三種通道組合在一起,便成了我們最終能看到的顏色。它能表示的顏色數(shù)目多到驚人,能涵蓋人眼能感知的所有色彩范圍。但是它無法表示顏色對人眼的吸引程度。那讓我們回想以上兩張圖,我們是不是一下子就被亮麗的藍色和黃色給吸引了?注意,我用了亮麗這個詞。
那什么是亮麗?答案是色彩的飽和度,也就是鮮艷度。以及恰到好處的色彩明度,也就是色彩的亮度。以及足夠多的色彩數(shù)目,也就是該顏色或者顏色族所代表的像素個數(shù)。
綜合來看,就是色彩飽和度越高,越鮮艷,越能吸引眼球。適當(dāng)?shù)拿鞫纫灿兄谔岣呱饰?,過低的話色彩很暗,過高的話色彩趨近白色,都會讓人眼忽略。至于色彩數(shù)目就不用多言,肯定越多越好嘛!
對圖片色彩模式有過研究的同學(xué)肯定能猜出來我要說什么了。沒錯,就是用HSL色彩模式評價提示。飽和度就是HSL中的S(saturation),明度就是HSL中的L(lightness)。Palette的給出的解法就是用顏色的S和L值以及像素個數(shù)去評價一種顏色的得分。
而為了滿足不同的顏色提取需求(比如有人希望提取亮的顏色,有人希望提取飽和低的顏色),Palette把顏色目標(biāo)分成了六種。高亮度的Light類,普通亮度的Normarl類,暗亮度的Dark類。高飽和的Vibrant類,低飽和的Mute類。它們自由搭配可以得出六種模式:
LIGHT_VIBRANT_MODE (高亮度高飽和類)
VIBRANT_MODE(普通亮度高飽和類)
DARK_VIBRANT_MODE(暗亮度高飽和類)
LIGHT_MUTED_MODE(高亮度低飽和類)
MUTED_MODE(普通亮度低飽和類)
DARK_MUTED_MODE(暗亮度低飽和類)
每種顏色目標(biāo)模式都有自己獨特的Target參數(shù),也就是S和L越靠近這個Target值得分越高,最終再綜合像素個數(shù)的得分,得分最高的顏色也就是我們在對應(yīng)模式下要提取的目標(biāo)顏色。
(2)怎么解決顏色分散問題?
另外一個難題就是顏色分散,畢竟RGB值完全相等的情況太少了。比如藍天,靠近太陽的地方會更白更亮,遠離太陽的地方藍色會更純更飽和。太分散的情況下,很容易藍色會輸給顏色相對更集中的其他顏色,如海邊的長滿綠色植被的山。這個時候,我們需要用一個框把這些相近卻不相同的藍色給框在一起,然后計算他們的平均顏色,來代表它們,這就是Palette中VBox的概念。進一步了解VBox,移步我之前的分析文章[點擊查看]。
Palette解決了這兩大問題,讓識別效果變得更加精確!所以當(dāng)你需要去識別圖片的主色調(diào)時,別忘了Palette。
4.怎么使用iOS-Palette?
在iOS-Palette中,我采用了跟TTAVPlayer[了解更多,點擊查看]一樣的設(shè)計思想:“保證最小的接入成本同時保證最大的擴展性”。對于絕大部分需求,你不需要去了解PaletteTarget,什么高亮度低飽和這樣的概念,你只需要調(diào)用這些簡單的API:


即可獲得回調(diào):

但是當(dāng)你需要更多的顏色模式時,你可以使用

并且還可以使用 | 分隔符去滿足不同的搭配需求,當(dāng)你需要所有模式的下的目標(biāo)顏色時,請使用:ALL_MODE_PALETTE,快捷獲取所有模式的顏色。這些數(shù)據(jù)將會在回調(diào)Block中的allModeColorDic的字典中帶回來。
Tips:推薦顏色的邏輯是優(yōu)先選VIBRANT_MODE下的顏色,如果該模式下沒有識別出目標(biāo)顏色,則會按照MUTE_MODE------LIGHT_VIRANT_MODE ------LIGHT_MUTE_MODE------DARK_VIBRANT_MODE------DARK_MUTE_MODE的繼承順序進行傳遞。
5.Demo的效果一覽
(1)在白色背景干擾下的表現(xiàn)

(2).在黑暗環(huán)境下的表現(xiàn)

3.正常光照環(huán)境下的表現(xiàn)

由于每張圖都有點大,更多的效果圖可以點擊查看:
(1)[點擊查看]
(2)[點擊查看]
(3)[點擊查看]
(4)[點擊查看]
(5)[點擊查看]
(6)[點擊查看]
6.關(guān)于作者
知乎:https://www.zhihu.com/people/tang-di-78/activities
Github:https://github.com/tangdiforx/iOSPalette
簡書:http://www.itdecent.cn/p/01df6010dded