一文搞懂影片編解碼原理

嵌入式視覺發表於2023-01-12

影片編解碼演算法分為傳統演算法和基於深度學習的方法,本文主要介紹基於傳統演算法的影片編解碼技術的原理,部分內容和圖片參考網上技術部落格(連結已放在文章末尾)。

一,基本術語

數字影像的定義及理解可以參考這篇文章:數字影像處理筆記|一文搞懂數字影像基礎

  1. 顏色深度: 儲存每個畫素顏色的強度,需要佔用一定大小的資料空間,這個空間大小即為顏色深度,對於 RGB 色彩模型,顏色深度是 24 (8*3)bit。
  2. 圖片解析度: 影像的畫素的數量,通常表示為寬*高。
  3. 影像/影片寬高比: 單地描述了影像或畫素的寬度和高度之間的比例關係。
  4. 位元率: 播放一段影片每秒所需的資料量,位元率 = 寬 * 高 * 顏色深度 * 幀每秒。例如,一段每秒 30 幀,每畫素 24 bits,解析度是 480x240 的影片,如果我們不做任何壓縮,它將需要 82,944,000 位元每秒或 82.944 Mbps (30x480x240x24)。當位元率幾乎恆定時稱為恆定位元率(CBR);但它也可以變化,稱為可變位元率(VBR)。

下面這個圖形顯示了一個受限的 VBR,當幀為黑色時不會花費太多的資料量。

image

1.1,顏色亮度和我們的眼睛

因為人眼睛的視杆細胞(亮度)比視錐細胞多很多,所以一個合理的推斷是相比顏色,我們有更好的能力去區分黑暗和光亮。

我們的眼睛對亮度比對顏色更敏感,可以看看下面的圖片來測試。

image

看不出左圖的方塊 A 和方塊 B 的顏色是相同的,那是因為我們的大腦玩了一個小把戲,這讓我們更多的去注意光與暗,而不是顏色。右邊這裡有一個使用同樣顏色的聯結器,那麼我們(的大腦)就能輕易分辨出事實,它們是同樣的顏色。

二,影片編碼的實現原理

2.1,影片編碼技術概述

編碼的目的是為了壓縮,所謂編碼演算法,就是尋找規律構建一個高效模型,將影片資料中的冗餘資訊去除。

常見的影片的冗餘資訊和對應的壓縮方法如下表:

種類 內容 壓縮方法
空間冗餘 畫素間的相關性 變換編碼,預測編碼
時間冗餘 時間方向上的相關性 幀間預測,運動補償
影像構造冗餘 影像本身的構造 輪廓編碼,區域分割
知識冗餘 收發兩端對人物共有認識 基於知識的編碼
視覺冗餘 人對視覺特性 非線性量化,位分配
其他 不確定性因素

影片幀冗餘資訊示例如下圖所示:

image

2.2,幀型別

我們知道影片是由不同的幀畫面連續播放形成的,影片的幀主要分為三類,分別是(1)I 幀;(2)B 幀;(3)P 幀。

  • I 幀(關鍵幀,幀內編碼): 是自帶全部資訊的獨立幀,是最完整的畫面(佔用的空間最大),無需參考其它影像便可獨立進行解碼。影片序列中的第一個幀,始終都是I幀
  • P 幀(預測): “幀間預測編碼幀”,需要參考前面的I幀和/或P幀的不同部分,才能進行編碼。P幀對前面的P和I參考幀有依賴性。但是,P幀壓縮率比較高,佔用的空間較小。
  • B 幀(雙向預測): “雙向預測編碼幀”,以前幀後幀作為參考幀。不僅參考前面,還參考後面的幀,所以,它的壓縮率最高,可以達到200:1。不過,因為依賴後面的幀,所以不適合實時傳輸(例如視訊會議)。

I 幀的處理,是採用幀內編碼(幀間預測)方式,只利用本幀影像內的空間相關性

P 幀的處理,採用幀間編碼(前向運動估計),同時利用空間和時間上的相關性。簡單來說,採用運動補償(motion compensation)演算法來去掉冗餘資訊。

image

2.3,幀內編碼(幀內預測)

幀內編碼/預測用於解決單幀空間冗餘問題。如果我們分析影片的每一幀,會發現許多區域是相互關聯的

image

舉個例子來理解幀內編碼,如下圖所示的圖片,可以看出這個圖大部分割槽域顏色是一樣的。假設這是一個 I 幀 ,我們即將編碼紅色區域,假設幀中的顏色在垂直方向上保持一致,這意味著未知畫素的顏色與臨近的畫素相同

image

這樣的先驗預測雖然會出錯,但是我們可以先利用這項技術(幀內預測),然後減去實際值,算出殘差,這樣得出的殘差矩陣比原始資料更容易壓縮。

image

2.4,幀間編碼(幀間預測)

影片幀在時間上的重複,解決這類冗餘的技術就是幀間編碼/預測。

嘗試花費較少的資料量去編碼在時間上連續的 0 號幀和 1 號幀。比如做個減法,簡單地用 0 號幀減去 1 號幀,得到殘差,這樣我們就只需要對殘差進行編碼

image

image

做減法的方法比較簡單粗暴,效果不是很好,可以有更好的方法來節省資料量。首先,我們將0 號幀 視為一個個分塊的集合,然後我們將嘗試將 幀 1 和 幀 0 上的塊相匹配。我們可以將這看作是運動預測

運動補償是一種描述相鄰幀(相鄰在這裡表示在編碼關係上相鄰,在播放順序上兩幀未必相鄰)差別的方法,具體來說是描述前面一幀(相鄰在這裡表示在編碼關係上的前面,在播放順序上未必在當前幀前面)的每個小塊怎樣移動到當前幀中的某個位置去。”

image

如上圖所示,我們預計球會從 x=0, y=25 移動到 x=7, y=26xy 的值就是運動向量進一步節省資料量的方法是,只編碼這兩者運動向量的差。所以,最終運動向量就是 x=7 (6-0), y=1 (26-25)。使用運動預測的方法會找不到完美匹配的塊,但使用運動預測時,編碼的資料量少於使用簡單的殘差幀技術,對比圖如下圖所示:

image

三,實際的影片編碼器如何工作

3.1,影片容器(影片資料封裝)

首先影片編碼器和影片容器是不一樣的,我們常見的各種影片檔名字尾:.mp4.mkv.avi.mpeg 等其實都是影片容器。影片容器定義:將已經編碼壓縮好的影片軌和音訊軌按照一定的格式放到一個檔案中,這個特定的檔案型別即為影片容器。

3.2,編碼器發展歷史

影片編碼器的發展歷史見下圖:

image

3.3,通用編碼器工作流程

雖然影片編碼器的已經經歷了幾十年的發展歷史,但是其還是有一個主要的工作機制的。

3.3.1,第一步-圖片分割槽

第一步是將幀分成幾個分割槽子分割槽甚至更多。分割槽的目的是為了更精確的處理預測,在微小移動的部分使用較小的分割槽,而在靜態背景上使用較大的分割槽。

通常,編解碼器將這些分割槽組織成切片(或瓦片),宏(或編碼樹單元)和許多子分割槽。這些分割槽的最大大小對於不同的編碼器有所不同,比如 HEVC 設定成 64x64,而 AVC 使用 16x16,但子分割槽可以達到 4x4 的大小。

image

3.3.2,第二步-預測

有了分割槽,我們就可以在它們之上做出預測。對於幀間預測,我們需要傳送運動向量和殘差;至於幀內預測,我們需要傳送預測方向和殘差

3.3.3,第三步-轉換

在我們得到殘差塊(預測分割槽-真實分割槽)之後,我們可以用一種方式變換它,這樣我們就知道哪些畫素我們應該丟棄,還依然能保持整體質量。這個確切的行為有幾種變換方式,這裡只介紹離散餘弦變換(DCT),其功能如下:

  • 畫素轉換為相同大小的頻率係數塊
  • 壓縮能量,更容易消除空間冗餘。
  • 可逆的,也意味著你可以還原回畫素。

我們知道在一張影像中,大多數能量會集中在低頻部分,所以如果我們將影像轉換成頻率係數,並丟掉高頻係數,我們就能減少描述影像所需的資料量,而不會犧牲太多的影像質量。 DCT 可以把原始影像轉換為頻率(係數塊),然後丟掉最不重要的係數。

我們從丟掉不重要係數後的係數塊重構影像,並與原始影像做對比,如下圖所示。

image

可以看出它酷似原影像,與原圖相比,我們丟棄了67.1875%,而如何智慧的選擇丟棄係數則是下一步要考慮的問題。

3.3.4,第四步-量化

當我們丟掉一些(頻率)係數塊時,在最後一步(變換),我們做了一些形式的量化。這一步,我們選擇性地剔除資訊(有損部分)或者簡單來說,我們將量化係數以實現壓縮

如何量化一個係數塊?一個簡單的方法是均勻量化,我們取一個塊並將其除以單個的值(10),並舍入值。

image

那如何逆轉(反量化)這個係數塊呢?可以透過乘以我們先前除以的相同的值(10)來做到。

image

均勻量化並不是一個最好的量化方案,因為其並沒有考慮到每個係數的重要性,我們可以使用一個量化矩陣來代替單個值,這個矩陣可以利用 DCT 的屬性,多量化右下部,而少(量化)左上部,JPEG 使用了類似的方法,我們可以透過檢視原始碼看看這個矩陣

3.3.5,第五步-熵編碼

在我們量化資料(影像塊/切片/幀)之後,我們仍然可以以無損的方式來壓縮它。有許多方法(演算法)可用來壓縮資料:

  1. VLC 編碼
  2. 算術編碼

3.3.6,第六步-位元流格式

完成上述步驟,即已經完成影片資料的編碼壓縮,後續我們需要將壓縮過的幀和內容打包進去。需要明確告知解碼器編碼定義,如顏色深度,顏色空間,解析度,預測資訊(運動向量,幀內預測方向),檔次*,級別*,幀率,幀型別,幀號等等更多資訊。

參考資料

  1. digital_video_introduction
  2. 零基礎,史上最通俗影片編碼技術入門

相關文章