https://github.com/ShiqiYu
=================================================
知乎關於人臉識別實時濾鏡討論:
映客直播中 人臉特效是基於人臉識別還是AR?有什么可以使用的SDK么?
鏈接:https://www.zhihu.com/question/52892092/answer/205076802
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
本人來說說該這是如何實現的吧。關鍵字:人臉檢測+圖片 + opengles。
我來說說Android上面是如何實現的吧。通過Camera接口獲取預覽數據,然后將圖像所在的Surface綁定到opengles 的EGLSurface中,opengles通過從Surface中讀取EXTERNAL_OES類型的紋理Texture到幀緩沖區Framebuffer中(即將相機的圖像幀讀入FBO中),然后就是通過opengles將png 或者其他格式的圖片貼紙讀入生成相應的紋理Texture。有了貼紙的Texture,接下來就是將貼紙繪制到幀緩沖區Framebuffer中。繪制完成,通過eglSwapBuffers將EGLSurface中渲染完成的幀交換顯示到前台,這就是問題中所貼出來的預覽界面。
上面流程幾乎所有有貼紙特效的相機、直播推流端等應用都基本走的流程,不管是不是用ffmpeg做推流,特效這塊,基本上都需要接入opengles來做渲染,一方面是減少CPU使用,降低能耗,降低發熱量,另一方面是渲染速度,gpu專門做渲染這一塊的,在實時渲染方面,CPU軟實時渲染的效率是完全不夠的。這個過程需要什么支撐?那就是人臉檢測技術,我將貼紙紋理渲染到預覽幀中,需要拿到准確的人臉關鍵點,這個是必須的。人臉檢測基本上都是用opencv來檢測的,也有第三方的SDK可以接入,比如Face++,美顏相機等存在貼紙特效的應用幾乎都在用這個,可以免費試用,自己從頭開發的話,准確率和檢測時間是個大問題,人臉關鍵字檢測的算法比較成熟了,但傳統的算法跑在手機上還是做一些調整的,尤其是這種實時渲染的,得至少控制在一幀(16ms)內,因為除了檢測,我們還需要做其他的渲染,比如美顏、美白、磨皮、瘦臉等,哪怕是用opengles來做,也是勉強夠用而已。舉個例子,美顏相機的貼紙相機,在1080P分辨率的手機上,默認Texture 的大小也僅僅是480 x 864(存在虛擬鍵)、540 x 960(不存在虛擬鍵),也就是說,預覽幀的分辨率是這么大的,而不是屏幕的1080P(目前市面上的美顏類相機,預覽幀(Camera PreviewSize)幾乎沒有達到1080P的,都是渲染完成后在放大的。除了美顏相機, Camera360的預覽texture是764 x 1024, 全屏是720 x 1280,但顯示則是1080 x 1440、1080 x 1920,各家的相機流程差不多,渲染方案的話有單FBO 和多FBO兩種,Camera360 就是單一FBO渲染的,美顏相機則是多FBO渲染的)。渲染完成后再放大顯示到屏幕上的,因為美顏相機處理做貼紙,還做了實時美顏、磨皮、美白、瘦臉、瘦下巴、放大眼睛等操作,這些操作都是非常耗時的,哪怕是這樣,美顏相機在紅米Note2 上渲染出來的實時預覽幀率也只面前到20幀,Nexus 5X 實時預覽幀率大約23幀左右。大部分手機的預覽幀率最大支持值在30fps左右,能夠拿來做渲染的時間還是非常不足的。
那么有沒有相關的開源項目呢?有的,比如比較出名的相機項目MagicCamera就是其中一個,github地址: wuhaoyu1990/MagicCamera 你可以參考下。貼紙跟濾鏡的渲染過程是一樣的,其中多了個人臉關鍵點檢測,也就是說,在用opengles繪制貼紙之前,需要做相關的定位、貼紙的三維位置調整,比如人臉朝向,貼紙要跟着人臉朝向繪制,否則方向是不對的。人臉朝向的話,也有專門的算法,但是如果要做到實時渲染,那么在人臉檢測之后再做人臉朝向的話,效率就太低了,這里面可以用檢測的關鍵點簡單結算得到朝向的,比如簡單地用人的眼睛位置,通過Math.atan2(distX, distY),通過眼睛中心點的距離(distX, distY)算方位角,雖然准確率不夠,而且考慮的因素也不全,但在實時渲染預覽情況下也沒有更好的辦法,因為你首先得保證預覽的幀率。得到人臉朝向的方位角后,我們就可以拿着這個方位角對貼紙的位置繞Y軸旋轉,通過對投影矩陣旋轉得到三維物體在二維平面上的坐標位置,再對貼紙進行渲染。這樣就能夠做到立體感的貼紙了。
基本上做完上面的一些處理,