2026年10月12日 星期一

NV12 vs YUV vs NV21

 NV12 是 YUV 格式的一種特定記憶體排列變體。

簡單來說,「YUV」是一個大分類(泛指所有將亮度與色度分開的色彩空間),而「NV12」則是這個大分類下,屬於 YUV 4:2:0 取樣、且採用半平面(Semi-Planar)記憶體排列的一種具體標準。
它們的關係可以透過以下三個核心維度來理解:

1. 隸屬與取樣關係 (Subsampling)

  • YUV:包含 4:4:4、4:2:2、4:2:0 等多種色度抽樣比例。
  • NV12:固定屬於 YUV 4:2:0。這代表水準與垂直方向都每 2×2(共 4 個)像素的 Y(亮度),共用一組 U 和 V(色度)。每像素平均只佔用 1.5 位元組 (12 bits)。

2. 記憶體排列方式 (Layout)

這是 NV12 與其他 YUV420 格式(如 I420)最大的差別。NV12 採用半平面(Semi-Planar)架構,在記憶體中分為兩個平面(Plane):
  • Plane 1 (Y 平面):連續存放所有像素的 Y(亮度)資料。
  • Plane 2 (UV 平面):將 U 和 V 資料交錯(Interleaved)存放在一起,順序為 U, V, U, V...。

記憶體排列表現樣張(以 4×2 像素為例):

[Y0][Y1][Y2][Y3][Y4][Y5][Y6][Y7]  <- 第一平面:全部都是 Y
[U0][V0][U1][V1]                  <- 第二平面:UV 交錯排列

3. 直觀對比:NV12 與其他常見 YUV 格式

為了讓你更清楚 NV12 在 YUV 大家族中的位置,以下直接與其他常見格式進行對比:
格式名稱YUV 取樣比例記憶體架構分類記憶體實際排列順序常用場景
NV124:2:0Semi-Planar (半平面)YYYYYYYY 接著 UVUVDirect3D、Android、硬體解碼 (GPU)
NV214:2:0Semi-Planar (半平面)YYYYYYYY 接著 VUVUAndroid 相機預設 (Camera1 API)
I420 (YU12)4:2:0Planar (全平面)YYYYYYYY 接著 UU 接著 VV軟體視訊通訊 (WebRTC, FFmpeg)
YUY2 (YUYV)4:2:2Packed (打包交錯)Y0 U0 Y1 V0 Y2 U2 Y3 V2USB 視訊鏡頭、早期影音擷取卡

為什麼 NV12 這麼受歡迎?

在現代作業系統與顯示卡(如 Intel、NVIDIA、AMD 的硬體加速解碼)中,NV12 是最被廣泛支援的內部格式。
因為它的 Y 平面與 UV 平面是分開的,顯示卡在渲染時可以直接把 Y 平面當成一張灰階紋理(Texture),UV 平面當成另一張色彩紋理,在晶片內部直接進行硬體級的色彩轉換(轉成 RGB 顯示),處理效率極高。
如果你正在編寫程式,需要知道如何將 RGB 矩陣打包成 NV12 的雙平面記憶體結構,或是需要 NV12 轉 RGB 的轉換公式,我們可以進一步討論!

NV21 是另一種極為常見的數位視訊編碼格式,屬於 YUV 4:2:0 採樣的 Semi-Planar(半平面) 結構。它最著名的身分是 Android 系統相機(Camera API)預設的預覽畫面格式。 [1, 2, 3]

基本特性

  • 採樣格式:YUV 4:2:0。意味著橫向與縱向的色度(UV)都經過減半抽樣,每 4 個 Y(2x2 的像素區塊)共同分享一組 UU 和 VV。 [4, 5]
  • 儲存平面(Two-Plane):
    1. 第一個平面(Plane 1):連續存放整張圖像所有的 Y(亮度) 資料。
    2. 第二個平面(Plane 2):將 V(Cr)和 U(Cb) 進行交錯(Interleaved)存放。 [6, 7, 8]
  • 位元組順序(Byte Order):在 UV 平面中,它是以 V, U, V, U 的順序排列(這也是它被稱為 NV21 的原因,V 在 U 前面)。 [1, 9]
  • 資料大小:平均每個像素僅佔 12 bits(1.5 個位元組),檔案體積比 YUY2(16 bits)小了 25%,非常利於網路傳輸與硬體解碼。 [4, 10]

NV21 與 NV12 的直接對比

這兩者經常被放在一起討論,因為它們的結構高達 99% 相同,唯一的差別在於 UV 平面的排列順序相反: [6, 11]
特性NV21NV12
YUV 採樣YUV 4:2:0 Semi-PlanarYUV 4:2:0 Semi-Planar
Y 平面先存放所有 Y先存放所有 Y
UV 平面順序V, U, V, U, V, U...(VU 交錯)U, V, U, V, U, V...(UV 交錯)
主要陣營Android 生態系相機預設格式iOS (Apple)、Windows (DirectX) 慣用格式

記憶體排列範例(以 4×2 像素的影像為例)

當影像讀入記憶體時,連續的位元組(Byte)呈現方式如下:
  • NV21:[Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8] + [V1, U1, V2, U2]
  • NV12:[Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8] + [U1, V1, U2, V2] [1, 4, 10]

應用與常見痛點

由於 NV21 是 Android 底层硬體直接吐出來的資料,許多行動端的影像演算法(如 OpenCV 影像處理、人臉辨識、AI 濾鏡模型)都會直接指定 NV21 作為輸入格式。 [5]
不過,如果你要把 Android 採集到的 NV21 影片流直接丟給跨平台播放器(如 Windows、iOS),或丟進視訊編碼器(如 H.264 標準通常偏好 I420/YU12 或 NV12),就必須在軟體層做一次 VU 順序對調(將 NV21 轉為 NV12),否則畫面中的人會集體「面色鐵青」,紅藍色調完全相反。 [1, 5]

沒有留言:

NV12 vs YUV vs NV21