【數據壓縮】Exp01.彩色空間轉換——YUV2RGB

【一】.基本原理

這次的實驗是將yuv格式的圖像轉換爲rgb格式。兩種彩色空間互相轉換的公式如下:

1.RGB轉YUV:

Y=0.2990*R+0.5870*G+0.1140*B
U=-0.1684*R+-0.3316*G+0.5*B
V=0.5*R-0.4187*G-0.0813*B

2.YUV轉RGB:

R = Y+(R-Y) = Y+1.14075(V-128)
G = Y+(G-Y) = Y-0.7169(V-128)-0.3455(U-128)
B = Y+(B-Y) = Y+1.779(U-128)

爲了編程實現該功能,首先需要了解的是兩種不同格式的文件的數據是如何組織存儲的。本次實驗的yuv文件是採用4:2:0的採樣格式,即色差信號U和V相對於亮度信號Y而言是水平方向2:1,垂直方向2:1採樣的。它在文件中是按幀的順序,先存每一幀的Y分量,接着是U分量,最後是V分量,存完第一幀再按相同的格式存儲下一幀。而本實驗的RGB文件則是按照G、B、R的順序,從上到下,從左到右地依次存儲將每個像素點的G、B、R的值。

由於代碼較長,因此考慮將功能分塊,這樣可增強代碼的可讀性而且便於後期代碼的管理。

【二】.實驗流程分析

在運行程序之前需要對project的一些參數進行設置,main函數的參數有四個,分別爲輸入的文件名,輸出的文件名,圖像的寬,圖像的高,並將工作路徑設爲輸入文件所在的路徑:

第一次運行程序,發現程序雖然通過了編譯和鏈接,但在程序運行過程中,main函數中文件讀取中的打印消息打印出來了,但在之後程序運行便崩掉了,因此可能是在調用yuv2rgb這個子函數時出現了問題。經過仔細的檢查之後發現,是因爲u和v信號的上取樣時,其中的指針賦初值時出現了問題。

sq_ubuf和sq_vbuf這兩個指針是用來指向上取樣後的UV分量,因此它們的初始值不應該與u_buffer和v_buffer指針的地址有關,且上取樣時劃紅線的兩行代碼忘記加1,導致每四個像素中的第三個像素重複賦值,而第四個像素沒有賦值,因此程序不能正常運行。發現該問題後,定義了兩個新的指針變量:

修正代碼後程序能夠正常運行,併成功生成.rgb文件,將該生成的文件用給定的rgb2yuv程序轉換爲.yuv格式後用yuvplayer播放器查看,效果圖如下:

上面的圖爲原始yuv圖像,下面的圖爲由程序轉換後得到的yuv圖像,可以清楚地看到圖像上有一些噪點,說明程序還是存在問題。初步猜測可能是在進行數據類型強制轉換時出現了問題。經過轉換公式計算後得到的浮點數的範圍可能並不一定咋在0到255之間,將其強制轉換爲範圍在0到255之間的unsigned char型數據會導致數據出錯,因此定義了三個浮點型的中間變量,用來判斷經轉換公式計算得到的數是否在0到255的範圍內,若不在此範圍內則將超出範圍的數據強制置爲0或255:

代碼經過修改後得到的.rgb文件再經過轉換得到的.yuv文件如下:

可以看到噪點已經都被消除,與源圖像幾乎已無差別。

【三】.實驗代碼及其分析

下面爲修改後的最終代碼:

main.app

yuv2rgb.app

yuv2rgb.h

【四】.實驗結果及分析

這次實驗共用了三張不同的yuv圖像進行測試,結果如下:

通過上列圖像可以看出,由於對計算後的數據進行了範圍的判斷以及相應的處理,因此不同亮度的圖像都能正常地轉換得到預期的結果。

【五】.結論

通過這次的實驗,不僅熟悉了編程語言,更重要的是在調試代碼的過程中學會如何去找錯誤和修正錯誤。在編程的過程中找錯誤是一個非常重要的能力,只有學會如何去找出錯誤纔有可能得到最後想要的結果。除此之外,用整體的眼光看待問題、分析問題也是十分重要的,這些都是需要我在之後的學習鍛鍊中不斷積累與成長的地方。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章