轉(zhuǎn)載自 : https://blog.csdn.net/weekend_y45/article/details/124972039
本文主要大體談?wù)勔曨l編碼壓縮的原理誊薄。視頻原始數(shù)據(jù)是非常大的,如果不進(jìn)行編碼壓縮的話,不管是存儲還是傳輸都將非常的麻煩。因此為了解決這個問題秸仙,就出現(xiàn)非常多的編碼壓縮方法和格式裹芝,H264、H265泻帮、VP8、VP9 和 AV1等等都是市面上常見的編碼標(biāo)準(zhǔn)都弹。不過編碼壓縮的核心原理和準(zhǔn)則是大同小異的娇豫。
一、視頻圖像存在的冗余
視頻是一幀幀圖像組成的畅厢,圖像一般是有數(shù)據(jù)冗余的锤躁,主要包括以下 4 種:
1、空間冗余或详。比如說將一幀圖像劃分成一個個 16x16 的塊之后,相鄰的塊很多時候都有比較明顯的相似性郭计,這種就叫空間冗余霸琴。
2、時間冗余昭伸。一個幀率為 25fps 的視頻中前后兩幀圖像相差只有 40ms梧乘,兩張圖像的變化是比較小的,相似性很高庐杨,這種叫做時間冗余选调。
3、視覺冗余灵份。我們的眼睛是有視覺靈敏度這個東西的仁堪。人的眼睛對于圖像中高頻信息的敏感度是小于低頻信息的。有的時候去除圖像中的一些高頻信息填渠,人眼看起來跟不去除高頻信息差別不大弦聂,這種叫做視覺冗余。
4氛什、信息熵冗余莺葫。我們一般會使用 Zip 等壓縮工具去壓縮文件,將文件大小減小枪眉,這個對于圖像來說也是可以做的捺檬,這種冗余叫做信息熵冗余∶惩可以理解為為了表達(dá)同樣的內(nèi)容堡纬,所用的表達(dá)方式是否啰嗦,比如對于一串字符串a(chǎn)aabbbb萨脑,如果采用3a4b來表達(dá)隐轩,就簡略了一些。
視頻編碼就是通過減少上述 4 種冗余來達(dá)到壓縮視頻的目的渤早。
二职车、編碼壓縮的核心準(zhǔn)則和思路
對于一個 YUV 圖像,我們把它劃分成一個個 16x16 的宏塊(以 H264 為例),Y悴灵、U扛芽、V 分量的大小分別是 16x16、8x8积瞒、8x8川尖。這里我們只對 Y 分量進(jìn)行分析(U、V 分量同理)茫孔。假設(shè) Y 分量這 16x16 個像素就是一個個數(shù)字叮喳,我們從左上角開始之字形掃描每一個像素值,則可以得到一個“像素串”缰贝。如下圖所示:
有一種編碼方式叫做行程編碼馍悟,就是將類似 “bbbaaaaddddd” 壓縮成 “3b4a5d”,字符串由 12 個字符壓縮到 6 個字符剩晴。如果我們對圖像宏塊掃描出來的這個“像素串”做同樣的行程編碼操作锣咒,是不是也有可能減小圖像塊呢?答案是肯定的赞弥。但是這里有個問題是如果字符串是交替出現(xiàn)毅整,比如adcdcabdc這種,沒有多少連續(xù)的字符的話绽左,那么壓縮就沒有意義了悼嫉。所以,最好是有很多連續(xù)的字符拼窥,這樣壓縮才有意義承粤。而且如果連續(xù)的這個字符是個占用空間很小的字符那就更好了。比如0闯团,因為0在二進(jìn)制中只占1個位辛臊。
所以,編碼壓縮的核心準(zhǔn)則就是房交,盡可能地使得像素值串出現(xiàn)很多的字節(jié)占用空間較小的連續(xù)的像素值彻舰,這樣就可以方便壓縮,且壓縮效果較好候味。
那么如何做到呢刃唤?下面繼續(xù):
三、減少圖像的空間冗余和時間冗余
上面我們也說到白群,圖像內(nèi)部相鄰宏塊之間有很多相似性尚胞,并且兩張圖像之間也有很多相似性。因此帜慢,根據(jù)圖像的這個特點笼裳,我們可以在編碼的時候進(jìn)行幀內(nèi)預(yù)測和幀間預(yù)測唯卖。
幀內(nèi)預(yù)測就是在當(dāng)前編碼圖像內(nèi)部已經(jīng)編碼完成的塊中找到與將要編碼的塊相鄰的塊。一般就是即將編碼塊的左邊塊躬柬、上邊塊拜轨、左上角塊和右上角塊,通過將這些塊與編碼塊相鄰的像素經(jīng)過多種不同的算法得到多個不同的預(yù)測塊允青。
然后我們再用編碼塊減去每一個預(yù)測塊得到一個個殘差塊橄碾。最后,我們?nèi)∵@些算法得到的殘差塊中像素的絕對值加起來最小的塊為預(yù)測塊颠锉。而得到這個預(yù)測塊的算法為幀內(nèi)預(yù)測模式法牲。
由于這個殘差塊中像素的絕對值之和最小,這個殘差塊的像素值經(jīng)過掃描之后的“像素串”就比直接掃描編碼塊的“像素串”中的像素值更接近 0 了琼掠。
同理皆串,幀間預(yù)測也是一樣的。我們在前面已經(jīng)編碼完成的圖像中眉枕,循環(huán)遍歷每一個塊,將它作為預(yù)測塊怜森,用當(dāng)前的編碼塊與這個塊做差值速挑,得到殘差塊,取殘差塊中像素值的絕對值加起來最小的塊為預(yù)測塊副硅,預(yù)測塊所在的已經(jīng)編碼的圖像稱為參考幀姥宝。
預(yù)測塊在參考幀中的坐標(biāo)值 (x0, y0) 與編碼塊在編碼幀中的坐標(biāo)值 (x1, y1) 的差值 (x0 - x1, y0 - y1) 稱之為運動矢量。而在參考幀中去尋找預(yù)測塊的過程稱之為運動搜索恐疲。事實上編碼過程中真正的運動搜索不是一個個塊去遍歷尋找的腊满,而是有快速的運動搜索算法的。這個算法在這里就不展開闡述培己。
總之碳蛋,通過預(yù)測得到的殘差塊的像素值相比編碼塊的像素值,去除了大部分空間冗余信息和時間冗余信息省咨,這樣得到的像素值更小肃弟。如果把這個殘差塊做掃描得到的像素串送去做行程編碼,這樣相比直接拿編碼塊的像素串去做編碼更有可能得到更大的壓縮率零蓉。
但是我們的目標(biāo)不只是將像素值變小笤受,而是希望能出現(xiàn)連續(xù)的,該如何去做呢敌蜂?下面繼續(xù):
四箩兽、DCT變化和量化
這個主要是利用我們?nèi)搜鄣囊曈X敏感性的特點。我們上面講到人眼對高頻信息不太敏感章喉。因為人眼看到的效果可能差別不大汗贫,所以我們可以去除一些高頻信息身坐。
為了分離圖像塊的高頻和低頻信息,我們需要將圖像塊變換到頻域芳绩。常用的變換是 DCT 變換掀亥。DCT 變換又叫離散余弦變換。在 H264 里面妥色,如果一個塊大小是 16x16 的搪花,我們一般會劃分成 16 個 4x4 的塊(當(dāng)然也有劃分成 8x8 做變換的,我們這里以 4x4 為例)嘹害。然后對每個 4x4 的塊做 DCT 變換得到相應(yīng)的 4x4 的變換塊撮竿。
變換塊的每一個“像素值”我們稱為系數(shù)。變換塊左上角的系數(shù)值就是圖像的低頻信息笔呀,其余的就是圖像的高頻信息幢踏,并且高頻信息占大部分。低頻信息表示的是一張圖的總體樣貌许师。一般低頻系數(shù)的值也比較大房蝉。而高頻信息主要表示的是圖像中人物或物體的輪廓邊緣等變化劇烈的地方。高頻系數(shù)的數(shù)量多微渠,但高頻系數(shù)的值一般比較写罨谩(注意不是所有的高頻系數(shù)都一定小于低頻,只是大多數(shù)高頻系數(shù)比較谐雅琛)檀蹋。如下圖所示(黃色為低頻,綠色為高頻):
這樣做完了 DCT 變換之后云芦,低頻和高頻信息就分離開來了俯逾。由于低頻信息在左上角,其余的都是高頻信息舅逸。那么如果我們對變換塊的像素值進(jìn)行“之字形”掃描桌肴,這樣得到的像素串,前面的就是數(shù)值比較大的低頻系數(shù)琉历,后面就是數(shù)值比較小的高頻部分识脆。
由于人眼對高頻信息不太敏感,如果我們通過一種手段去除掉大部分高頻信息善已,也就是將大部分高頻信息置為 0灼捂,但又不太影響人的觀感,是不是就可以達(dá)到我們最初的目標(biāo)换团,即可以得到有一連串 0 的像素串悉稠?這就涉及到量化操作了。
我們讓變換塊的系數(shù)都同時除以一個值艘包,這個值我們稱之為量化步長的猛,也就是 QStep(QStep 是編碼器內(nèi)部的概念耀盗,用戶一般使用量化參數(shù) QP 這個值,QP 和 QStep 一一對應(yīng)卦尊,你可以自行去網(wǎng)上查詢一下轉(zhuǎn)換表)叛拷,得到的結(jié)果就是量化后的系數(shù)。QStep 越大岂却,得到量化后的系數(shù)就會越小忿薇。同時,相同的 QStep 值躏哩,高頻系數(shù)值相比低頻系數(shù)值更小署浩,量化后就更容易變成 0。這樣一來扫尺,我們就可以將大部分高頻系數(shù)變成 0筋栋。如下圖所示:
解碼的時候,我們會將 QStep 乘以量化后的系數(shù)得到變換系數(shù)正驻,很明顯這個變換系數(shù)和原始沒有量化的變換系數(shù)是不一樣的弊攘,這個就是我們常說的有損編碼。而到底損失多少呢姑曙?
這由 QStep 來控制襟交,QStep 越大,損失就越大渣磷。QStep 跟 QP 一一對應(yīng),也就是說確定了一個 QP 值授瘦,就確定了一個 QStep醋界。所以從編碼器應(yīng)用角度來看,QP 值越大提完,損失就越大形纺,從而畫面的清晰度就會越低。同時徒欣,QP 值越大系數(shù)被量化成 0 的概率就越大逐样,這樣編碼之后碼流大小就會越小,壓縮就會越高打肝。
五脂新、熵編碼
這是視頻編碼壓縮的最后一步,也是真正實現(xiàn)“壓縮”的一步粗梭,前面的幾步是一個預(yù)熱争便,是為了最后一步的壓縮能達(dá)到最大效益的一個預(yù)處理。這一步主要是去除信息熵冗余断医,就比如在上面所講的行程編碼滞乙,就是一種簡單的熵編碼奏纪,上面的例子讓需要12個字符才能表達(dá)的內(nèi)容用6個字符就表達(dá)完了。
熵編碼有很多斩启,且有分為可變長編碼序调,如哈夫曼編碼、香農(nóng)-費諾編碼編碼兔簇、指數(shù)哥倫布編碼等发绢;以及算術(shù)編碼,如CAVLA、CABAC织鲸、指數(shù)編碼诬烹。這些熵編碼的目的都是一樣,就是去除信息熵冗余甚纲,達(dá)到壓縮的目的,就如簡單的行程編碼類似朦前。
熵編碼的方法很多介杆,這里不再一一闡述,本文的核心主要是集中在原理韭寸,和大體的思路春哨。
總結(jié):
至此,視頻編碼的原理和思路就如上所述了恩伺「氨常總結(jié)下來可以理解為幾步:
1、預(yù)測(幀內(nèi)預(yù)測晶渠,幀間預(yù)測):為了去除空間冗余和時間冗余凰荚;
2、DCT變化和量化:為了去除視覺冗余褒脯;
3便瑟、熵編碼:為了去除信息熵冗余。