在OpenGL中利用shader進行實時瘦臉大眼等臉型微調[转]

转自https://www.twblogs.net/a/5b8656982b71775d1cd4fa93

在OpenGL中利用shader進行實時瘦臉大眼等臉型微調

在現在這個靠臉吃飯的時代,如果你沒有一張瓜子臉一雙大眼睛,那還怎麼去吃飯呢,而現在一些直播視頻App相機應用基本都會有瘦臉大眼效果.本文是在OpenGl環境下,在shader中通過對像素位置進行偏移來實現放大縮小的,實現起來快速簡單,也是各大主流應用裁劉德基本方式.

舉個栗子

首先在這裏給大家看一個效果圖

 

其實從圖像中大家就能明白原理了,座標經過平方處理之後,本來A點應該取A1像素,結果取的是A2像素,也就是離中心0.25位置的像素B1被放在了離中心0.5的位置A上,這顯然就是放大的操作.由於橫縱座標一一對應,所以該算法並不會造成像素的丟失,只是會在放大區域的邊緣內有一部分像素比較密集的區域.

上面的分析是建立在特殊值下的,我們再回到這個函數本身, 
curve 是我們的pow函數的次方值,由於我們考慮的都是[0,1]區間的,所以該值越大,離中心點向外擴散也越厲害,放大效果越大. 
intensity 的取值是[0,1]當它取1時就是我們上面分析的情況,會最大化的利用pow次方產生的座標偏移來取像素,若它爲0,則不會產生任何縮放效果,intensity 是一個影響因子,一個對 pow函數產生的座標偏移的採用度,intensity越大則會更大化利用 pow 函數產生座標便宜作爲最後的座標偏移.

圓內縮小

vec2 narrowFun(vec2 curCoord,vec2 circleCenter,float radius,float intensity,float curve)
{
    float currentDistance = distance(curCoord,circleCenter);

    {
        float weight = currentDistance/radius;
        weight = 1.0-intensity*(1.0-pow(weight,curve));//默認curve 爲2 ,當curve 越大時, 會縮小得越小的,
        weight = clamp(weight,0.0001,1.0);
        curCoord = circleCenter+(curCoord-circleCenter)/weight;
    }
    return curCoord;
}

上面分析了圓內放大,看一下縮小的代碼,其實也不難理解,也是利用pow函數進行像素座標的偏移.這裏就不多家分析了.

向某一點拉伸

// 拉伸
vec2 stretchFun(vec2 textureCoord, vec2 originPosition, vec2 targetPosition, float radius,float curve)
{
    vec2 offset = vec2(0.0);
    vec2 result = vec2(0.0);

    vec2 direction = targetPosition - originPosition;


    float infect = distance(textureCoord, originPosition)/radius;

    infect = pow(infect,curve);// 默認 curve 爲1,這個值越大,拉伸到指定點越圓潤,越小越尖
    infect = 1.0-infect;
    infect = clamp(infect,0.0,1.0);
    offset = direction * infect;
    result = textureCoord - offset;

    return result;
}

輸入:座標,拉伸中心座標,拉伸目標座標,拉伸半徑,拉伸算法參數. 
返回:放大之後應該取的像素的位置.

拉伸和縮放原理其實是一樣的,只是理解起來有些差距.我們還是設 curve = 2,對其原理進行分析.

 

上圖是我對拉伸原理的一個簡單描述,A爲拉伸中心座標,B爲拉伸目標座標,經過拉伸後,圓1上的像素會被平移到圓1’,圓2上的像素會被平移到圓2’.以A爲圓心的同心圓經過拉伸之後都會被平移,離A越近平移的距離越遠,A點直接平移到B點, 而R處則不會平移.看到這裏應該已經知道怎樣將一個圓臉變成瓜子臉了吧.當然這都是微調,如果調整過大會產生不自然的效果.curve 值越大,拉伸到指定點越圓潤,越小越尖.

上面只是我對人臉變形時的原理進行分析,要想使用變形,首先要確定人臉特徵點,有了這些特徵點,你才知道縮放中心半徑等等,而使用時往往不是一步就能達到理想效果,比如說我們大眼 一般是首先對一個比較大的包含眼睛的區域進行放大,然後再對眼睛中心瞳孔位置進行進一步放大.實際使用時爲了達到某種效果一般都是對這幾種操作進行組合使用,而且是多次操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值