iOS 眼睛放大(三)

Finn
Feb 4, 2022

--

最後一回我們將介紹優化的放大算法,並實際套入專案中,最後也有附上呈現效果與Demo

放大算法

放大方法中我們需要有

  • 中心點:眼睛中心(放大圓心)
  • 範圍半徑:眼睛範圍

透過 Vision 我們可以得到眼睛周圍以及瞳孔位置,要取得範圍,最簡單方式是將最長兩點距離的點當作直徑,以瞳孔為中心

如果想放大區域內圖片,就要畫上離中心更近的距離的顏色,也就是說 fragement sharder function 要做的事就是

取得離中心點更近並同方向的座標,並回傳該座標顏色

左圖 是將藍與紅點個別拿取離中心較近的顏色渲染 就會有放大效果 (右圖)
如果 weight < 1 會是放大的效果,weight > 1 則會縮小

假若直接等比例放大則會使眼睛範圍邊界有不自然的切割感

直接等比例放大

我們可以透過 Interactive Image Warping 中下面的 scaling 公式來消除切割感

這個方法簡單來說,越靠近圓邊,則取得的位置會越接近與原本位置,來達到視覺上的平滑

公式會回傳更新後與圓心的距離,例如原本位置距離圓心為 0.8,帶入公式後假如得到 0.2 ,代表就是回傳該方向距離位置的顏色來顯示

4.4.2 Local scaling
  • fs(r) : 最後會得到的距離
  • r : 目前與中心距離
  • r max : 範圍半徑
  • a : 表示強度 instensity (大於0 為放大,小於0 為縮小)

由下面表格發現,在越接近邊緣時會越收斂

在強度為 0.5 情況下 與圓心距離的變化

套入公式

於是我們將剛剛公式套入 fragement 中,並且加入左眼與右眼

首先我們先定義由外面帶入 Uniform 的 struct,並且新增了左右兩眼的眼睛範圍與兩眼的瞳孔,以及強度

從外面帶入的 struct

若在放大瞳孔放大範圍內,則套用公式取得新的位置

取得所要顯示新的位置

最後在 fragment function 裡判斷是否在左右眼範圍內,是的話則透過上面 enlargePosition function 將目前顯示座標改為偏移後的座標,若在範圍外則顯示原本座標

Enlarge fragment shader function

成果

可以補上一個 slider 調整 instensity 的縮放大小

instensity -0.5 ~ 1.5的效果

當然也可以用在相機錄影上,只要透過 GPUImage camera 的 delegate 將影像 pixelBuffer 給 Vision 接著與 Image 處理方式一樣

總結

透過 Vision 臉部偵測 與 GPUImage Metal 繪製來達到簡單的眼睛放大效果,但也有些缺點,就是與目前商用訓練模型的臉部偵測精準度與特徵數量上有差距,以及再根據部位的放大方法可以再加強,例如眼睛放大範圍貼合度,而非單純的使用原形,會使得眼睛細長在放大部分會變得很不自然(甚至將眉毛變形)

Demo

參考網站

Interactive Image Warping

Metal Shading Language

--

--