日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Metal之探究理解视频渲染RGB与YUV颜色编码

發(fā)布時間:2024/5/21 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Metal之探究理解视频渲染RGB与YUV颜色编码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、顏色編碼

① RGB 顏色編碼

  • RGB 三個字母分別代表了 紅、綠、藍,這三種顏色作為三個基底顏色,將它們以不同的比例相加,可以產(chǎn)生多種多樣的顏色。
  • RGB 圖像中,每個像素點都有紅、綠、藍三個基底顏色,其中每種原色都占用 8 bit,也就是一個字節(jié)(0-255),那么一個像素點也就占用 24 bit,也就是三個字節(jié)。

  • 在圖像顯示中,一張 1280 * 720 大小的圖片,就代表著它有 1280 * 720 個像素點。其中每一個像素點的顏色顯示都采用 RGB 編碼方法,將 RGB 分別取不同的值,就會展示不同的顏色,就占用 1280 * 720 * 3 / 1024 / 1024 = 2.63 MB 存儲空間。

② YUV 顏色編碼

  • YUV 是指亮度參量色度參量分開表示的像素格式,而這樣分開的好處就是不但可以避免相互干擾,還可以降低色度的采樣率而不會對圖像質(zhì)量影響太大。
  • YUV 顏色編碼采用的是明亮度色度來指定像素的顏色。
  • Y表示明亮度(Luminance、Luma) U 和 V 表示色度(Chrominance、Chroma)而色度又定義了顏色的兩個方面:色調(diào)和飽和度。
    • Y 通道數(shù)值越高,圖片則越亮;
    • U 通道數(shù)值越高,顏色就越接近藍色;
    • V 通道數(shù)值越高,顏色就越接近紅色。
  • YUV 顏色編碼格式在默認情況下是圖像和視頻壓縮的標準。
  • 和 RGB 表示圖像類似,每個像素點都包含 Y、U、V 分量。但是它的 Y 和 UV 分量是可以分離的,如果沒有 UV 分量一樣可以顯示完整的圖像,只不過是黑白的,如下圖所示:

  • 對于 YUV 圖像來說,并不是每個像素點都需要包含了 Y、U、V 三個分量,根據(jù)不同的采樣格式,可以每個 Y 分量都對應(yīng)自己的 UV 分量,也可以幾個 Y 分量共用 UV 分量。

二、RGB 與 YUV 的相互轉(zhuǎn)換

  • 對于圖像顯示器來說,它是通過 RGB 模型來顯示圖像的,而在傳輸圖像數(shù)據(jù)時又是使用 YUV 模型,這是因為 YUV 模型可以節(jié)省帶寬。因此就需要采集圖像時將 RGB 模型轉(zhuǎn)換到 YUV 模型,顯示時再將 YUV 模型轉(zhuǎn)換為 RGB 模型。
  • RGB 到 YUV 的轉(zhuǎn)換,就是將圖像所有像素點的 R、G、B 分量轉(zhuǎn)換到 Y、U、V 分量。公式如下:
    Y = 0.299 * R + 0.587 * G + 0.114 * B
    U = -0.147 * R - 0.289 * G + 0.436 * B
    V = -0.615 * R - 0.515 * G - 0.100 * B
  • YUV 到 RGB 的轉(zhuǎn)換如下:
    R = Y + 1.14 * V
    G = Y - 0.39 * U - 0.58 * V
    B = Y + 2.03 * U
  • 此時的轉(zhuǎn)換結(jié)束后,每個像素點都有完整的 Y、U、V 分量。而之前提到 Y 和 UV 分量是可以分離的,接下來通過不同的采樣方式,可以將圖像的 Y、U、V 分量重新組合。
  • 不同采樣格式都是在一張圖像所有像素的 RGB 轉(zhuǎn)換到 YUV 基礎(chǔ)上進行的。

三、采樣方式

  • YUV 的優(yōu)點之一是,色度頻道的采樣率可比 Y 頻道低,同時不會明顯降低視覺質(zhì)量。有一種表示法可用來描述 U 和 V 與 Y 的采樣頻率比例,這個表示法稱為 A:B:C 表示法。

① YUV 4:4:4 采樣

  • 表示色度頻道沒有下采樣, 每個 Y 分量對應(yīng)自己的 UV 分量。
  • 其中的 Y、U、V 三個分量的采樣比例是相同的,所以每個像素點的分量信息都是完整的,每個分量占用 8bit,一個像素點占用 1 個字節(jié)。與 RGB 顏色編碼相比,并沒有節(jié)省帶寬,占用的存儲空間也沒有減少。

  • 假設(shè)原始圖像的像素為(一對[]表示一個像素點):
    [Y0, U0, V0]; [Y1, U1, V1]; [Y2, U2, V2]; [Y3, U3, V3];
  • 將原始圖像像素按照YUV4:4:4采樣的碼流為(相對原始像素是原樣輸出):
    Y0, U0, V0, Y1, U1, V1, Y2, U2, V2, Y3, U3, V3
  • 最后映射還原的像素點 = 原始圖像的像素,為:
    [Y0, U0, V0]; [Y1, U1, V1]; [Y2, U2, V2]; [Y3, U3, V3];
  • 可以看到這種采樣方式的圖像和 RGB 顏色模型的圖像大小是一樣,并沒有達到節(jié)省帶寬的目的,當將 RGB 圖像轉(zhuǎn)換為 YUV 圖像時,也是先轉(zhuǎn)換為 YUV 4:4:4 采樣的圖像。

② YUV 4:2:2 采樣

  • 表示 2:1 的水平下采樣,沒有垂直下采樣。
  • 對于每兩個 U 樣例或 V 樣例,每個掃描行都包含四個 Y 樣例。
  • 兩個 Y 分量共用一套 UV 分量,意味著 UV 分量是 Y 分量采樣的一半,Y 分量和 UV 分量按照 2 : 1 的比例采樣。如果水平方向有 4 個像素點,那么采樣了 4 個 Y 分量,而只采樣了 2 個 UV 分量。

  • 每采樣一個像素點,都會采樣 Y 分量,而 U、V 分量則會間隔一個采集一個;
  • 假設(shè)原始圖像的像素為(一對[]表示一個像素點):
    [Y0, U0, V0]; [Y1, U1, V1]; [Y2, U2, V2]; [Y3, U3, V3];
  • 將原始圖像像素按照 YUV4:2:2 采樣的碼流為:
    Y0, U0, Y1, V1, Y2, U2, Y3, V3
  • 最后映射還原的像素點為:
    [Y0, U0, V1]; [Y1, U0, V1]; [Y2, U2, V3]; [Y3, U2, V3];
  • 采樣的碼流映射為像素點,還是要滿足每個像素點有 Y、U、V 三個分量。但是可以看到,第一和第二像素點公用了 U0、V1 分量,第三和第四個像素點公用了 U2、V3 分量,這樣就節(jié)省了圖像空間。

③ YUV 4:2:0 采樣

  • 表示 2:1 的水平下采樣,2:1 的垂直下采樣。 4個Y分量共用一套UV分量。
  • YUV 4:2:0 采樣,并不是指只采樣 U 分量而不采樣 V 分量。而是指,在每一行掃描時,只掃描一種色度分量(U 或者 V),和 Y 分量按照 2 : 1 的方式采樣。
  • 第一行掃描時,YU 按照 2 : 1 的方式采樣,那么第二行掃描時,YV 分量按照 2:1 的方式采樣。
  • 對于每個色度分量來說,它的水平方向和豎直方向的采樣和 Y 分量相比都是 2:1 。
  • 在田字格的 4 個像素點中,4 個 Y 分量共用了一套 UV 分量,如圖所示

  • 假設(shè)原始圖像的像素為(一對[]表示一個像素點):
    [Y0, U0, V0]; [Y1, U1, V1]; [Y2, U2, V2]; [Y3, U3, V3];
    [Y5, U5, V5]; [Y6, U6, V6]; [Y7, U7, V7]; [Y8, U8, V8];
  • 將原始圖像像素按照YUV4:2:0采樣的碼流為:
    Y0, U0, Y1, Y2, U2, Y3,
    Y5, V5, Y6, Y7, V7, Y8,
  • 最后映射還原的像素點為:
    [Y0, U0, V5]; [Y1, U0, V5]; [Y2, U2, V7]; [Y3, U2, V7];
    [Y5, U0, V5]; [Y6, U0, V5]; [Y7, U2, V7]; [Y8, U2, V7];
  • 從映射出的像素點中可以看到,四個 Y 分量是共用了一套 UV 分量,而且是按照 2*2 的小方格的形式分布的,相比 YUV 4:2:2 采樣中兩個 Y 分量共用一套 UV 分量,這樣更能夠節(jié)省空間。

④ YUV 4:1:1 采樣

  • 表示 4:1 的水平下采樣,沒有垂直下采樣。對于每個 U 樣例或 V 樣例,每個掃描行都包含四個 Y 樣例。
  • 與其他格式相比,4:1:1 采樣不太常用,本文不對其進行詳細討論

四、YUV 存儲格式

① 平面格式與打包格式

YUV 格式可以分為打包格式和平面格式。在打包格式中,Y、U 和 V 組件存儲在一個數(shù)組中。像素被組織到了一些巨像素組中,巨像素組的布局取決于格式。在平面格式中,Y、U 和 V 組件作為三個單獨的平面進行存儲。

  • planar 平面格式:
    指先連續(xù)存儲所有像素點的 Y 分量,然后存儲 U 分量,最后是 V 分量。
  • packed 打包模式:
    指每個像素點的 Y、U、V 分量是連續(xù)交替存儲的。

② 基于 YUV 4:2:2 采樣的格式

常見的基于 YUV 4:2:2 采樣的格式如下:YUYV 格式、UYVY 格式、YUV 422P 格式。

  • YUYV 格式
    YUYV 格式是采用打包格式進行存儲的,指每個像素點都采用 Y 分量,但是每隔一個像素采樣它的 UV 分量,排列順序如下:
    Y0 UO Y1 V0 Y2 U2 Y3 V2
    (Y0 和 Y1 公用 U0 V0 分量,Y2 和 Y3 公用 U2 V2 分量….)
  • UYVY 格式
    UYVY 格式也是采用打包格式進行存儲,它的順序和 YUYV 相反,先采用 U 分量再采樣 Y 分量,排列順序如下:
    U0 Y0 V0 Y1 U2 Y2 V2 Y3
    (Y0 和 Y1 公用 U0 V0 分量,Y2 和 Y3 公用 U2 V2 分量….)
  • YUV 422P 格式
    YUV 422P 格式,又叫做 I422,采用的是平面格式進行存儲,先存儲所有的 Y 分量,再存儲所有的 U 分量,再存儲所有的 V 分量。

③ 基于 YUV 4:2:0 采樣的格式

  • 基于 YUV 4:2:0 采樣的格式主要有 YUV 420P 和 YUV 420SP 兩種類型,每個類型又對應(yīng)其他具體格式。
YUV 420P 類型YUV 420SP 類型
YV12 格式NV12 格式
YU12 格式NV21 格式
  • YUV 420P 和 YUV 420SP 都是基于 Planar 平面模式 進行存儲的,先存儲所有的 Y 分量后, YUV420P 類型就會先存儲所有的 U 分量或者 V 分量,而 YUV420SP 則是按照 UV 或者 VU 的交替順序進行存儲了,具體查看看下圖:

  • YUV420P 的格式:

五、RGB 與YUV 轉(zhuǎn)換矩陣的幾何含義

  • YUV 與 RGB 的轉(zhuǎn)換公式不止一種,主要原因是具體格式下,標準不同,這里采用蘋果 Demo 中給出的轉(zhuǎn)換矩陣,其它轉(zhuǎn)換公式中,具體數(shù)值可能不同:
let ycbcrToRGBTransform = float4x4(simd_float4(+1.0000, +1.0000, +1.0000, +0.0000),simd_float4(+0.0000, -0.3441, +1.7720, +0.0000),simd_float4(+1.4020, -0.7141, +0.0000, +0.0000),simd_float4(-0.7010, +0.5291, -0.8860, +1.0000));
  • 將上面向量與矩陣乘法寫成行列式形式,可能更符合大家的直覺:
R = Y + 1.402*V - 0.701 G = Y - 0.3441*U - 0.7141*V + 0.5291 B = Y + 1.772*U - 0.886
  • 可以發(fā)現(xiàn),這個 YUV 轉(zhuǎn) RGB 的公式其實是個線性變換,用幾何的方式表達就是說:
    • 將一個 RGB 的顏色用 xyz 坐標表示,那么將這個坐標(旋轉(zhuǎn)、縮放、平移)之后,新的 xyz 坐標就可以表示 YUV 顏色值;
    • 反之也是,將一個 YUV 顏色分量當做 xyz 坐標,那么將這個坐標逆向(旋轉(zhuǎn)、縮放、平移)之后,新的 xyz 坐標就可以表示 RGB 顏色值;
  • 于是,可以在 3D 空間中畫一個邊長為 1 的正方體,后方左下角(0, 0, 0) 就代表黑色,前方右上角(1, 1, 1) 就代表白色,如下圖右下角立方體。同樣復(fù)制一個,并將其坐標用矩陣轉(zhuǎn)換到 YUV 空間,如下圖左上角傾斜的長方體。

  • 對于 RGB 的立方體,比較簡單:它的 x 坐標越大,越往右方,顏色越紅;y 坐標越大,越往上方,顏色越綠;z 坐標越大,越往前方,顏色越藍。
  • 而 YUV 的長方體,它的 x 坐標越大,越往右方,亮度越大;y 坐標越大,越往上方,顏色從黃到藍;z 坐標越大,越往前方,顏色從青綠到紅。

let box1 = scene.rootNode.childNode(withName: "box", recursively: true)! let box2 = scene.rootNode.childNode(withName: "box2", recursively: true)! simpleProgram(node: box1) simpleProgram(node: box2)// YUV 到 RGB let ycbcrToRGBTransform = float4x4(simd_float4(+1.0000, +1.0000, +1.0000, +0.0000),simd_float4(+0.0000, -0.3441, +1.7720, +0.0000),simd_float4(+1.4020, -0.7141, +0.0000, +0.0000),simd_float4(-0.7010, +0.5291, -0.8860, +1.0000) ); let p = ycbcrToRGBTransform.inverse//RGB 到 YUV box1.simdTransform = p// box2.simdTransform = box2.simdTransform * ycbcrToRGBTransform.inverse * box2.simdTransform.inverse // 用 shader 進行可視化顯示 func simpleProgram(node:SCNNode) {let program = SCNProgram()program.vertexFunctionName = "vertexShader"program.fragmentFunctionName = "fragmentShader"// 賦值給**SCNGeometry**或者**SCNMaterial**guard let material = node.geometry?.materials.first else { fatalError() }material.program = program } // 默認的頭文件 #include <metal_stdlib> using namespace metal; // 與 SceneKit 配合使用時,需要的頭文件 #include <SceneKit/scn_metal>struct VertexInput {float3 position [[attribute(SCNVertexSemanticPosition)]]; };struct ColorInOut {float4 position [[position]];float4 color; };struct MyNodeData {float4x4 modelViewProjectionTransform; };// 頂點著色器函數(shù),輸出為 ColorInOut 類型,輸入為 VertexInput 類型的變量 in,和 MyNodeData 類型的變量指針 scn_node vertex ColorInOut vertexShader(VertexInput in [[stage_in]], constant MyNodeData& scn_node [[buffer(0)]]) {ColorInOut out;// 將模型空間的頂點補全為 float4 類型,進行 MVP 變換out.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);// 加 0.5,將坐標從[-0.5~0.5],轉(zhuǎn)換到[0~1] 以代表顏色out.color = float4(in.position + 0.5, 1);return out; }// 片元著色器函數(shù),輸出為 half4,輸入為 ColorInOut 類型的變量 in fragment half4 fragmentShader(ColorInOut in [[stage_in]]) {return half4(in.color); }

六、總結(jié)

  • YUV4:4:4 中 Y、U、V 分量的采樣比例相同,既可以理解為原始圖像像素點原樣輸出,存儲空間沒有任何變化。
  • YUV4:2:2 采樣格式,是指每采樣一個像素點,都會采樣 Y 分量,而 U、V 分量則會間隔一個采集一個,本質(zhì)是通過左右相鄰像素點共用 U/V 分量。相比 RGB 顏色編碼格式,節(jié)省了 1/3 的存儲空間,同時節(jié)約了在傳輸時的帶寬。
  • YUV4:2:0 采樣格式,是實際開發(fā)中最常用的顏色編碼格式,相比 YUV4:2:2 采樣格式,更能節(jié)省空間。是指在 2*2 的田字格中有 4 個像素點,其中 4 個 Y 分量共用一套 UV 分量,其本質(zhì)是通過田字格的上下左右像素點共用 U/V 分量。

總結(jié)

以上是生活随笔為你收集整理的Metal之探究理解视频渲染RGB与YUV颜色编码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。