視頻算法分類
視頻處理算法基本上可以分為兩個大類:空域算法和時域算法。要想了解在每種情況下如何有效的處理數據,就必須熟悉各種不同的視頻處理方法。許多算法將空域處理技術和時域處理技術結合起來(稱為“時空處理”),以實現算法要求的結果。
空域處理可以按像素順序進行,也可以基於宏塊進行。每一個像素的處理都是在空域局部進行的。按照順序對每一個像素做處理然后產生一個輸出,從前一個或下一個像素產生輸出不會有結果累計效應。一個按像素順序處理的例子是從RGB到YCbCr的顏色空間轉換。通常,這種類型的計算可以在運行過程中數據到來時執行,而不必將源圖像數據存儲到外部存儲器中。
雖然是在空域局部進行,基於宏塊的算法一般需要一組像素數據才能產生結果。一個簡單的例子就是計算平均值,也就是說,用某個像素周圍相鄰的像素計算平均值對該像素進行低通濾波。一個更復雜的例子是,用5*5的二維卷積內核檢測圖像中的邊緣信息,並從周圍大量的像素中繪制出相關信息。在這些基於宏塊的算法中,需要將源圖像愛你個數據存儲在存儲器中,但是並不需要存儲整個視頻,因為每次只對幾行視頻數據進行運算也是可以接受的。如果這樣計算的話,用外部的SDRAM存儲視頻幀數據,和使用片內的更快、更小的一級緩存或者二級緩存作為行緩存相比,兩者有比較顯著的差異。
到目前為止,我們僅僅考慮了空域局部處理。而另一類算法則涉及空域全局處理。這些方法每次針對整個圖像或視頻幀進行處理,通常需要在L3幀緩存和L1源圖像數據存儲器和中間結果之間進行數據傳輸。空域全局算法的例子包括離散余弦變換DCT、搜索圖像內線段的Hough變換,以及直方圖均衡化算法(該算法依賴於在根據分析結構修改圖像之前對整幅圖像的分析)。
時域處理算法則盡量尋找各幀之間特定像素或像素區域中出現變化或者相似的地方。時域處理的一個例子是,通過行加倍或者濾波,將隔行場轉換為逐行掃描格式。這里,我們假定兩個隔行場在時間上足夠相近,這樣可以用一個場的內容產生“遺失”的一個場。如果不是這種情況,例如,有一個運動邊界或者場景改變,此時視頻輸出中會出現錯誤,但是預處理通常會弱化這種問題。
另一個例子也說明了時域處理的重要性,那就是視頻監控系統。在這樣的系統中,每一幀都要和前一幀進行比較,以確定兩者是否有足夠的差異達到“警報條件”。換句話說,這是一種算法,用來確定是否有物體在非預期的情況下發生跨越多個幀的移動、消失或者出現。
絕大多數視頻壓縮算法都將空域處理和時域處理結合起來,形成一個新的類別,稱為“時空處理”。在空域中,每個圖像幀被分解為若干個宏塊,也就是說16*16個像素的一個區域。然后再對這些宏塊進行跟蹤、逐幀比較,從中提取出運動估計和補償的近似值。
帶寬計算
為了揭示與運動估計需要的吞吐量有關的一些重要概念,讓我們花一點時間來粗略計算一下視頻的帶寬需求。
首先,我們來看逐行掃描VGA(640*480)CMOS傳感器,該傳感器連接到處理器的視頻接口,以每秒30幀的速率發送8比特4:2:2的YCbCr數據。
(640*480像素/幀) (2字節/像素) (30幀/秒)=18.4MB/秒
這就是進入處理器的原始數據的吞吐量。通常。每一行中還會有一些空白數據需要傳輸,這樣算來,實際的像素時鍾頻率大約為24MHz。通過使用每次輸出16比特(亮度和色度數據在同一時鍾周期輸出)的傳感器模式,需要的時鍾周期將變為原來的一半,但是總的數據吞吐量保持不變,因為視頻接口每個時鍾周期傳輸的數據是原來的兩倍。
現在,我們要轉向顯示這一方面,看一個可以顯示“RGB565”圖像的VGALCD顯示器。也就是說,每一個RGB像素值被封包為兩個字節,然后在LCD顯示屏上顯示出來。這里有一個細微的差別,LCD通常需要一個刷新率,一般在50-80Hz。因此除非我們使用單獨的具有片內幀存儲器的LCD控制器芯片,否則就需要以這個刷新率不斷的刷新顯示器,即使傳感器的數據變化率僅有30幀/秒。所以有下面的例子:
(640*480像素/幀) (2字節/像素) (75幀/秒)=46.08MB/秒
由於通常在每個時鍾周期內傳輸一個並行的RGB565數據,所以像素時鍾大約是25MHz。
視頻應用
下圖系統所示,在嵌入式視頻應用中,某些基本的視頻處理步驟是如何以各種組合形式存在的。在圖中,一個隔行掃描CMOS傳感器通過處理器的視頻接口發送一路4:2:2YCbCr格式的視頻流,然后經過去隔行處理和掃描速率轉換,再傳遞給某些處理算法,為輸出到LCD面板做好准備。這些准備包括色度重采樣、伽馬校正、顏色轉換、縮放、圖像混合,然后封包為適當的輸出格式以便在LCD面板上顯示。需要注意的是,這個系統僅僅是一個例子,在實際的系統中並不是所有的元件都是必需的。另外,圖中這些處理步驟也可能以不同的順序出現。
視頻流輸入到LCD輸出的流程實例,包括了各個處理階段
去隔行處理
當我們從一台輸出隔行NTSC數據的相機中得到視頻源數據時,通常需要對數據進行去隔行處理。這樣,奇數行和偶數行就交織排列在存儲器中,而不是分別在兩個獨立的視頻場緩存中。不僅高效的基於宏塊的視頻處理需要去隔行,而且以逐行掃描格式顯示隔行視頻時也是需要的。有許多種方法可以完成去隔行處理,每一種都有自身的優缺點。在這里介紹其中的一些方法。
或許最明顯的解決方案是源數據的場1(奇數掃描行)和場2(偶數掃描行),然后將兩個緩存數據交織在一起產生一個順序的掃描輸出緩存。雖然這種稱為編織的技術很常用,但是其缺點明顯,因為兩個場在時間上相隔大約60Hz,相當於16.7ms。因此這種技術僅僅適合於相對靜態的圖像幀,在具有高速運動內容的場景中是不合適的。
為了減弱這種人為的瑕疵,並降低系統帶寬,有時候只讀入場1,然后將其復制到場2所在的位置,並存儲到輸出緩存中,這往往也是可以接受的。這種“行復制”方法顯然降低了圖像分辨率,並會引起輸出圖像出現的放塊效應,所以通常會使用一些具有更多處理的方法。這些方法包括線性插值法、中值濾波法以及運動補償法等。
平均行,也稱為bob,就是對鄰近的奇數行上相同水平位置的像素取平均值,作為偶數行上對應位置的像素。這種方法還可以推廣到線性插值上,也就是對鄰近行上的像素取加權平均值(最高的權重分配給最近的像素),從而產生缺失的一行像素。這與垂直方向上的FIR濾波器是相似的。
除了FIR濾波器之外,利用中值濾波器也可以產生更好的去隔行結果。中值濾波是值用周圍相鄰的像素中處於中間的一個灰度級來代替每一個像素的亮度值,以此來消除圖像中的高頻噪聲。還有一種備選的去隔行方法是運動檢測和補償,利用這種方法可以基於一系列幀中運動的物體來改造去隔行技術。以上這些都是現在通常使用的最高級的一些去隔行技術。
掃描轉換速率
完成了視頻的去隔行處理后,就需要進行掃描率的轉換,這樣做的目的是為了保證輸入幀速率與輸出顯示的刷新速率相匹配。為了實現兩者的均衡化,某些場可能被丟棄,也可能被復制。當然,和去隔行處理一樣,為了消除突發幀傳輸產生的高頻人為噪聲,最好使用一些濾波器。
下面是一個具體的幀速率轉換的例子,也就是講一個24幀/秒的視頻流轉換為30幀/秒的視頻流,這是NTSC制式所要求的,屬於3:2下拉(pulldown)。例如,如果電影中每一幀在NTSC視頻系統中僅使用一次,那么一24幀/秒的速度錄制的電影在NTSC視頻系統放映時的速度將提高25%(即30/24)。因此,3:2下拉被認為是一個將24幀/秒視頻流轉換為30幀/秒視頻流的過程。實現方式是以一定的周期模式重復某些幀,如下圖:
3:2下拉幀重復模式
像素處理
正如上面討論的那樣,通常使用的視頻算法有許多種,基本可以分為空域和時域兩大類。一種特別常見的視頻算子是二維(2D)卷積內核,該算子常被應用於多種不同的圖像濾波中。
二維卷積
由於視頻流實際上是以特定速率運動的圖像序列,因此,圖像濾波器必須以足夠快的速度運算以便跟上輸入圖像的速度。這樣,就必須對圖像濾波器內核進行優化,以使其以最少的處理器周期執行圖像濾波。下面用一個基於二維卷積的簡單圖像濾波器為例進行詳細說明。
卷積是圖像處理中基本的運算之一。在二維卷積運算中,某個像素值是通過對其周圍最接近的像素亮度值加權和得到的。由於模板(mask)的周圍都是特定的像素,因此模板一般是奇數維數。模板的大小通常要比圖像小很多,常用的是3*3模板,因為該木板的計算量相對比較合理,但對檢測圖像的邊緣也足夠大了。不過,也應該注意到,5*5、7*7以及更大的模板也被廣泛應用。例如,相機的圖像處理中就用了11*11的內核來執行極其復雜的濾波運算。
3*3內核的基本結構如下圖a,下面舉例說明,圖像中第20行,第10列的像素卷積計算輸出結果如下:
Out(20,10)=A*(19,9)+B*(19,10)+ C*(19,11)+ D*(20,9)+ E*(20,10)+F*(20,11)+ G*(21,9)+ H*(21,10)+ I*(21,11)
重要的是如何選擇有利於計算的系數,例如,選擇系數為2的冪(包括小數)時是非常有利的,因為這時的乘法可以用簡單的以為操作來代替。
下圖b~e中是幾個有用的3*3內核。
b中的Delta函數是最簡單的圖像處理算法之一,直接保留當前像素而不做任何改動。
c是兩種流行的邊緣檢測模板,第一個用來檢測垂直邊緣,第二個用來檢測水平邊緣。輸出值越大,則代表着圖像中邊緣的梯度越大。
d中的內核是一個平滑濾波器,對周圍8個像素取平均值,然后將平均值放在當前像素位置上。這種操作會產生一種“平滑”的效果,或者說是對圖像進行低通濾波。
e中的濾波器被稱為“銳化模板”算子,該模板可以產生一種邊緣增強的圖像,主要方法是用當前像素減去該像素的平滑版本(通過計算周圍8個像素的平均值得到)。
3*3卷積模板及其具體方法
處理圖像邊界
當類似於二維卷積運算的處理發生在圖像邊界區域時,會出現什么情況?為了正確的進行像素的濾波,就需要一些處於邊界之外的像素信息。對於這種情況,有一些校正的措施,最簡單的就是忽略這些邊緣區域。也就是說,一個5*5卷積內核需要當前像素上下左右各2行(或列)像素才能正確的計算。因此,為什么不忽略每個方向的兩行圖像數據,以保證內核總是對真是的數據執行運算呢?當然這也不總是理想的方法,因為它忽略了一些真是的圖像數據。另外,當幾種濾波器串聯在一起使用以產生更復雜的像素處理算法時,這種策略就會不斷的縮窄輸入到下一級濾波器的輸入圖像。
處理圖像邊界的其他一些較為流行的方法是復制幾行或幾列像素,或者從左邊界(上邊界)繞回到前面的右邊界(下邊界)。這些方法在實踐中是比較容易實現的,但他們會產生原來不存在的數據,因而在一定程度上破壞了濾波的結果。
或許最直接、破壞性最小的處理圖像邊界的方法是將位於實際圖像外部的所有像素看作全0值,即黑色。盡管這種方法也會使濾波結果產生一定的失真,但是卻不會像產生一些隨機的非零值像素那樣帶來侵害性的結果。
色度重采樣、伽馬校正和顏色轉換
前面已經討論過如何在4:4:4 YCbCr和RGB顏色空間之間進行轉換,轉換方式是3*3的矩陣乘法。但是,到目前為止,像素的格式仍然是在4:2:2YCbCr顏色空間。因此需要對色度信號進行重采樣,以得到4:4:4格式。然后就可以直接轉換到RGB空間了,就和前面已經看到的一樣。
從4:2:2到4:4:4的重采樣過程涉及一些插值運算,就是在那些沒有Cb和Cr色度分量的Y樣本處插入Cr和Cb分量。一種很明顯的重采樣方法是根據最近的相鄰像素取平均值作為遺失的色度值。也就是說,某個像素處遺失的Cb值用最近的兩的Cb的平均值來代替。在這些應用中,可能有必要使用高階濾波器,但通常這種簡化的方法已經足夠了。另一種方法是復制鄰近像素的相關色度值作為當前像素遺失的對應色度值。
一般情況下,從4:1:1空間轉換到4:2:2或4:4:4格式只需要使用一個一維濾波器。而從4:2:0格式重采樣轉換到4:2:2或4:4:4格式則涉及垂直采樣,因此必須使用一個二維卷積濾波內核。
由於色度重采樣和YCbCr到RGB空間轉換都是線性操作,所以有可能將多個步驟組合在一起構成一個數學處理步驟,這樣就可以更加有效的完成4:2:2YCbCr到RGB的轉換。
在這個階段,伽馬校正通常也是必須的。因為伽馬校正的非線性特性,所以最有效的實現方法是利用查找表,在顏色空間轉換之前進行伽馬校正。隨后,轉換過程的結果就會產生伽馬校正過的RGB分量,這是適合於輸出顯示的格式。
縮放與剪切
所謂縮放,就是輸出視頻流的分辨率與輸入視頻流不一致。在理想情況下,為了避免輸入視頻流和輸出視頻流之間任意的縮放操作,固定的縮放比例(輸入視頻分辨率和輸出面板分辨率)是事先定好的。
根據應用的不同,縮放可以是縮小,也可以是放大。很重要的一點是要理解要縮放的圖像的內容(例如,是否存在文本和細線)。不適合的縮放可能會導致文本無法識別,或者引起縮放后的圖像中原來的水平線消失了。
將輸入幀大小調整為更小的輸出幀,最容易的方法是剪切圖像。例如,如果輸入幀的大小是720*480像素,而輸出是VGA幀(640*480像素),你就可以剪切掉每一行中的前40個像素和后40個像素。這樣做的好處是,不管剪切還是復制圖像,都不會引入人為的干擾。當然,這樣也有缺點,就是每幀的內容會丟失80個像素(約11%)。有時候,這也不是什么嚴重的問題,因為屏幕的最左邊和最右邊包括最上邊和最下邊通常受顯示器邊框的影響而顯得很模糊。
如果不做剪切,還有其他幾種方法可以下采樣(減少像素或者行數)或者上采樣(增加像素或者行數)一副圖像,這樣允許在處理的復雜度和最終圖像質量之間進行權衡。
增加或減少每行的像素
一種直接的縮放方法是剪切像素(下采樣)或者復制現有像素(上采樣)。也就是說,當向下縮小到一個更低的分辨率時,每一行中有些像素(或某一幀中某些行)就被拋棄掉了。這確實降低了處理的負荷,但結果也會有一定的損失。
再復雜一點,使用線性插值可以改善圖像的質量。例如,縮小圖像時,對水平方向或者垂直方向進行濾波將得到一個新的輸出像素,然后用這個像素代替插值處理時用到的那些像素。與前面提到的技術一樣,這種方法也會損失一定的信息,並且圖像失真也是存在的。
如果圖像質量是最關鍵的因素,那么也有些其他的方法可以完成縮放,而不會降低圖像質量。這些方法將會根據水平和垂直縮放比例相應的保留圖像中的高頻成分,同時減弱了鋸齒效應。例如,假定一副圖像的縮放因子是Y:X,為了完成這個縮放,圖像將被上采樣(插值)Y倍,並過濾以便消除鋸齒,然后再下采樣(抽取)X倍,在實際應用中,這兩個采樣過程可以合並為一個多速率濾波器。
增加或減少每幀中的行數
增加或減少每行中的像素數量用到的方法一般也可以擴展到修改圖像中每幀的行數上。例如,丟棄相隔的行(或者說丟棄一個隔行掃描場)就是一種快速的降低垂直分辨率的方法。但是,正如在上面提到的,不管是移除還是復制行,可能需要某些形式的垂直濾波操作,因為這些處理過程在圖像中引入了人為的干擾。這里需要用到同樣的濾波器策略:簡單的垂直平均濾波、高階FIR濾波,或者用於垂直縮放到一個精確比例的多速率濾波器。
顯示處理
阿爾法混合
在顯示之前,常常需要將兩幅圖像或者兩個視頻緩存疊加在一起。這種情況的一個實際的例子是圖標的疊加,例如移動電話中顯示的信號強度、電池電量指示等。另外,還有一個涉及兩個視頻流的例子就是畫中畫功能。
當疊加兩個視頻流的時候,需要知道哪個流的內容要在上面顯示。這就是阿爾法混合的用武之地。阿爾法混合定義可一個alpha,用來表示疊加流和背景流之間的“透明度因子”,公式如下:
輸出值=alpha*(前景像素值) + (1-alpha)*(背景像素值)
從上面的公式中可以看出,alpha為0表示完全透明的疊加,alpha為1表示完全部透明的疊加,即忽略背景圖像。
有時候,alpha以單獨的通道隨着亮度和色度信息按像素順序一起發送。這就產生了一個新的表示法“4:2:2:4”,其中最后一個數字表示伴隨每一個4:2:2像素整體的alpha值。Alpha的編碼方式和亮度分量完全相同,但是對於絕大多數應用來說,一般只需要少量的離散透明度等級。有時候,視頻疊加緩存會預先與alpha相乘,或者通過查找表預先映射好,這種情況下,該視頻緩存稱為“成型”(shaded)視頻緩存。
混合
混合操作是將疊加緩存放置在更大的圖像緩存中。常見的例子是視頻顯示中的“畫中畫”模式,以及背景圖或者背景視頻中的圖標。一般來講,在輸出圖像完成之前,混合功能可以執行多次循環。換句話說,可能有許多“層”圖像和視頻結合在一起產生了一個混合的圖像。
二維DMA的傳輸能力對於混合操作而言是非常有用的,因為二維DMA可以將任意大小的矩形區域緩存放置到一個更大的緩存中。需要牢記的一點是,任何圖像剪切應該在混合操作之后進行,因為疊加的位置可能違反了新的剪切邊界。當然,一種替換方案是保證疊加一開始就不違反邊界,但是有時候這很難做到。
色度鍵控
術語“色度鍵控”(chroma keying)是這樣的一個過程,當兩幅圖像混合在一起的時候,疊加圖像中的內容代替了背景圖像中特定的顏色(通常為藍色或綠色)。這就提供了一種便利的方法,可以有目的地用第二幅圖像中適當的部分代替第一幅圖像中特定的部分。色度鍵控可以用媒體處理器中的軟件或硬件實現。作為一個相關的概念,當沒有獨立的alpha通道可用時,在疊加圖像中也可以用“透明色”(transparent color)來產生一個alpha=0的條件。
旋轉
許多情況下,在顯示之前還需要將輸出緩存中的內容進行旋轉。最常見的情況是,旋轉90度的整數倍。這是體現二維DMA非常有用的另外一個例子。
輸出格式
針對消費類應用的大多數彩色LCD顯示屏(TFT-LCD)具有數字RGB接口。顯示中的每一個像素實際上有3個子像素——紅綠藍,但人眼看到的是單個的彩色像素。例如,一個320*240像素的顯示屏實際具有960*240個像素分量,分別是R、G、和B子像素。每個子像素的位寬為8比特,這樣就構成了常用的24比特彩色LCD顯示屏的基礎。
3種最常用的配置分別是:每通道8比特的RGB888格式,每通道6比特的RGB666格式,R和B通道5比特、G通道6比特的RGB565格式。
RGB888在這3種格式中具有最高的色彩表現力。由於總共24比特的分辨率,這種格式可以提供1600萬種速度。在高性能的應用中,例如LCD電視,這種格式提供了高分辨率和精度。
RGB666格式在便攜式電子設備中應用比較普遍。這種格式可以提供262000種色度,總共有18比特分辨率。但是,由於18個引腳(6+6+6)的數據線不符合16比特處理器的數據路徑,因此,一種流行的行業折中方案是分別使用5比特表示R和B分量,而用6比特表示G(5+6+5=16比特數據總線),然后連接到RGB666顯示面板上。這種方式工作的很好,因為綠色是3種顏色中對視覺影響最重要的一種顏色。顯示面板中紅色和藍色的最低有效位連接到了各自的最高有效位。這就保證了每一個顏色通道都具有完全的動態范圍(從全亮到全黑)。