你知道微視背后的視頻特效技術是怎樣做出來的嗎?


歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~

本文由騰訊視頻雲終端團隊 發表於雲+社區專欄

常青, 2008 年畢業加入騰訊,一直從事客戶端研發相關工作,先后參與過 PC QQ、手機QQ、QQ物聯 等產品項目,目前在騰訊視頻雲團隊負責音視頻終端解決方案的優化和落地工作,幫助客戶在可控的研發成本投入之下,獲得業內一流的音視頻解決方案,目前我們的產品線包括:互動直播、點播、短視頻、實時視頻通話,圖像處理,AI 等等。

從眼睛的進化說起

大約在5億4千萬年前的寒武紀,地球上一部分生物體開始進化出了感光細胞,這種細胞可以感應光線的強弱,並且直接驅動本體的運動細胞采取必要的規避動作,以確保脆弱的細胞不被紫外線所傷。

后來單個的感光細胞開始扎堆聚集並且形成了凹陷,隨着凹陷程度的逐步加深,這些感光細胞也就漸漸地匯聚成了一個前部有孔隙的球狀結構,“眼球”的雛形也就由此形成了。

img

隨着球形的眼睛結構漸漸成型,中學物理課本中的“小孔成像”原理也就越來越能發揮作用:只要開孔足夠小,光線就能准確地到達這些聚集的感光細胞進而成像,眼前的物體也就開始變得邊界清晰。代表騰訊文化吉祥物之一的鸚鵡螺,就是采用了這種“以小為美”的進化策略,而且一直堅持到現在。

但是這種越來越小的策略也會導致光線進入量越來越小,所以鸚鵡螺們的世界想必是很昏暗的。我們的祖先可不希望放棄一個光明的世界,所以,我們給自己的眼睛安裝了一個足夠高級的光學部件 —— 晶狀體,以期擁有一個光明而清晰地世界。

然而,當大家都能把世界看得很清楚的時候,色彩分辨能力也就演變成了新一輪的軍備競賽。

當我們的祖先踩着那些堅稱“我就想健健康康地當個素食主義者”的同類屍體艱難前行的時候,他們並不知道,讓自己活得更久的原因,竟然是因為那雙能區分樹葉是嫩葉還是成熟葉片的眼睛。因為成熟的葉片常常包含大量的植物性毒素,會讓進食者身體遭受很大的傷害。所以,我們都是那一波“好色的”猴子的后代。

而眼睛對色彩的分辨能力,不僅在遠古時代讓我們活了下來,也讓今天衣食無憂的我們,能看到更多色彩斑斕的效果。比如短視頻的移形換影特效,其本質原理就是一個充分利用色彩的小把戲。

視頻內容

三原色的修改和組合

人體有三種視覺錐細胞,所以我們看到的顏色都是由三原色組成的,並不是說世界上就只有這些顏色,而是更加絢麗的色彩空間我們也感知不到。

因此,液晶顯示器的成像原理上也就是基於 R(紅)G(綠)B(藍) 三原色的組合而實現的,騰訊雲短視頻(UGSV)的移形換影特效,就是在這三種顏色空間上做了一些文章:

先以一幅靜態的圖片來舉例:

imgDoloris

現在把圖片中紅色的分量去掉,放大10%,再移動一些距離

imgDoloris-strip-red

再把藍色的分量去掉,放大10%,並移動一些距離

imgDoloris-strip-blue

再把綠色的分量去掉,放大10%,並移動一些距離

imgDoloris-strip-green

然后將這三副圖片以33%的透明度和源圖疊加到一起,形成一種移形幻影的效果

imgDoloris-blend

交給計算機來實現

上面這些圖片是我用圖片處理軟件簡單處理后得到的,但如果是視頻文件,顯然要交給計算機自動解決,如何做到呢?

首先我們先給這幅圖片定義坐標,為了方便處理我們將圖片的中心點定義為 (0,0),圖片的XY軸最大值為 1,如下圖所示:

img坐標定義

然后開始處理上面提到的兩個變換,一個是放大,一個是移動。

  • 放大 如果定義圖片上的任意象素坐標是(x,y),放大 s倍后的坐標就是 (x',y') = s(x,y) = (sx, sy)
  • 移動 如果定義圖片上的任意象素坐標是(x,y),將其移動(?x,?y),移動后的坐標就是(x',y') = (x+?x, y+?y)
  • 合並 將上面兩個公式進行合並,得到的新坐標點就是 (x',y') = (s(x+?x), s(y+?y))
  • 疊加 然后我們要將修改過的圖片疊加到原圖上,alpha疊加的公式是 src * (1 - alpha) + overlay * alpha

基於OpenGL的版本

短視頻的特效處理,每秒鍾要處理幾十張甚至更多的視頻畫面,所以簡單的 C 語言處理算法並不能滿足性能上的要求,我們需要使用手機的硬件加速能力,目前除了常見的 OpenGL 等 API 之外,還有如 Vulkan, DirectX, Metal 等可選方案。就目前而言,OpenGL 在各平台上通用性最好,網上的資料也比較豐富,不論是桌面平台還是移動平台都有支持,本文就以 OpenGL 來講講特效的實現。

實現移形換影特效的時候,我們會用到 OpenGL 的 Fragment Shader, Fragment Shader 作用就是返回圖像各點的色值,Fragment Shader也有一套自己的編程語言,叫 Shading Language 簡稱GLSL, GLSL 和 C 很像,增加了一些向量的數據類型,和一些圖像相關的處理函數。Shading 和 C 比起來有一個比較特殊的地方是不支持隱含的類型轉換,比如浮點點整型的轉換(在使用浮點數時,一定要加上小數點,如 1.0)。

篇幅原因,我不在這里把所有的特效代碼都一一列舉了,僅附上放大和位移的部分實現:

varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;

void main() {
	vec2 offset = vec2(0.05, 0.05);
	float scale = 1.1;
	vec2 coordinate;
	coordinate.x = (textureCoordinate.x - offset.x) / scale;
	coordinate.y = (textureCoordinate.y - offset.y) / scale;
	gl_FragColor = texture2D(inputImageTexture, coordinate);
}

考慮到不是所有讀者都學過 Shading Language,這里做一個簡單的解讀:

  • 我們在這里定義了一個變量 coordinate,這個就是前面提到的(x,y),它的值就是 ((x - ?x)/s, (y-?y)/s)
  • 函數 texture2D 的作用就是從圖片中獲取某個坐標的顏色。這里從 inputImageTexture 中的 coodinate 坐標點獲取了顏色。
  • gl_FragColor, 這是 Fragment Shader 的輸出的值, gl_FragColor是一個GLSL預定義的全局變量, 類型是vec4既 (r,g,b,a) 這四個量,也就是一個 RGBA 顏色。
  • 程序運行后在textureCoordinate這個坐標就會顯示gl_FragColor這個顏色。

上面講了單幅圖的處理,對於視頻我們可以做些更有意思的效果,比如我們可以把當前幀和上一幀的圖片進行疊加,這樣就可以作出一些更有意思的效果。

img

更多特效

本文介紹了騰訊雲短視頻(UGSV)眾多視頻特效中的一種,如果要實現更加復雜的特效,還是需要繼續深入研究 OpenGL 和人臉識別等相關領域的知識,這需要一段時間的學習和努力,也不可避免的需要踩很多坑。

那有沒有只需幾分鍾,就能一馬平川地搭快速搭建建帶有各種神奇特效的短視頻應用速成方案呢?

此文已由作者授權騰訊雲+社區發布,更多原文請點擊

問答
文字識別在格式上有什么要求?
相關閱讀
教你1天搭建自己的“微視”
教你從0到1搭建小程序音視頻
教你快速搭建一場發布會直播方案
雲學院 · 課程推薦 | 知乎KOL,與你分享機器學習中如何做選擇

搜索關注公眾號「雲加社區」,第一時間獲取技術干貨,關注后回復1024 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社區


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM