rgb計色系統是基於三基色原理的顏色計算系統,由紅光分量r、綠光分量g、藍光分量b可以混合出任意彩色光。在rgb檔案中,單個畫素的儲存形式為bgr順序。
yuv色彩空間通過乙個亮度訊號y和兩個色差訊號u、v來表示影象。yuv檔案通常是先儲存所有畫素的y分量,再儲存u分量、v分量。在4:2:0取樣格式中,y分量的大小是寬*高,u、v分量的大小是(寬/2)*(高/2),三個分量總的大小是寬*高*1.5。
本次實驗使用c語言完成了yuv影象到gb影象的轉換。
a. rgb->yuv
y = 0.299*r + 0.587*g + 0.114*b
u = 0.493*(b - y)
v = 0.877*(r - y)
b. yuv->rgb
r = y + 1.4075 *(v - 128)
g = y – 0.3455*(u - 128) - 0.7169 *(v - 128)
b = y + 1.779*(u - 128)
yuv2rgb函式通過動態指標、緩衝區對輸入的資料流進行操作。先為傳入的資料開闢緩衝區,再使用幾個動態指針對4:2:0取樣格式下的u、v分量進行上取樣,便於後續進行yuv到rgb的轉換。該函式中有兩個關鍵部分:
a. u、v分量的上取樣
上取樣對應下取樣,是插入資料的過程。由於yuv420p檔案的u、v分量的大小只有寬*高的1/4,在計算rgb時與寬*高大小的y分量對應起來比較困難,所以先對u、v分量進行了上取樣,把原來乙個單位的u(v)平攤成四個,得到了兩個寬*高大小的u、v資料流。(與之對應的,在rgb轉換yuv的過程中,要進行下取樣(抽取資料)操作。具體方法是將四個單位的u(v)求平均合成乙個,類似上圖的逆過程。)
b. yuv到rgb的轉換
&& fread(vbuf, 1, framewidth * frameheight / 4, yuvfile)) //將yuv檔案按順序分別讀取到ybuf、ubuf、vbuf中
fwrite(rgbbuf, 1, framewidth * frameheight * 3, rgbfile);//將資料寫入rgb檔案
printf("\r...%d", ++videoframeswritten);
} printf("\n%u %ux%u video frames written\n", videoframeswritten, framewidth, frameheight);
//關閉檔案,釋放緩衝區
free(rgbbuf);
free(ybuf);
free(ubuf);
free(vbuf);
fclose(rgbfile);
fclose(yuvfile);
return(0);
}2. yuv2rgb函式(yuv2rgb.cpp)
結合原理和示意圖,程式定義了六個動態指標來操作緩衝區(如上圖)。pu、pv分別指向上取樣前的u、v緩衝區,puu1(puv1)與puu2(puv2)分別指向了上取樣後u(v)緩衝區相鄰兩行對應位置的資料空間。上取樣的過程中,指標逐個後移,每當操作完各自的一行後,pu(pv)指標需要向後移寬/2,puu(puv)組指標分別需要向後移2*寬。具體實現過程在下段//upsample uv注釋後。
#include "stdlib.h"
#include "yuv2rgb.h"
static float yuvrgb14075[256];
static float yuvrgb03455[256];
static float yuvrgb07169[256];
static float yuvrgb1779[256];
int yuv2rgb (int x_dim, int y_dim, void *y_in, void *u_in, void *v_in, void *rgb_out)
// check to see if x_dim and y_dim are divisible by 2
if ((x_dim % 2) || (y_dim % 2)) return 1;
size = x_dim * y_dim;
y_buffer = (unsigned char *)y_in;
u_buffer = (unsigned char *)u_in;
v_buffer = (unsigned char *)v_in;
out = (unsigned char *)rgb_out;
up_u_buf = (unsigned char *)malloc(size * sizeof(unsigned char));
up_v_buf = (unsigned char *)malloc(size * sizeof(unsigned char));
//upsample uv
for(i=0;i255) *b=255;
else
if(g1>255) *g=255;
else
if(r1>255) *r=255;
else
b+=3;
y++;u++;v++;
} //釋放緩衝區
free(up_v_buf);
free(up_u_buf);
return 0;
}//查表法的原理是先將有限個數的轉換結果通過遍歷計算出來,待需要時跳過計算步驟使用查詢的方法從陣列中取出結果
//該方法在資料量大的時候能夠大大減少運算的時間
void initlookuptable()
實驗選擇了四個yuv影象檔案來進行yuv->rgb->yuv的轉換,分別比較了初始yuv檔案與經過兩次轉換後生成的yuv檔案。
以down.yuv(256*256)檔案為例,在實驗過程中,由於一開始沒有注意到unsigned char型別溢位的問題,導致轉換後的yuv影象有比較嚴重的失真(如下圖)。
後通過引入float型別的中間變數,對其值進行判斷後再轉換成unsigned char型別,使轉換後的yuv分量都不超過256,從而解決了上面產生的失真問題。
上圖中,左側為原yuv檔案,右側為轉換後的yuv檔案。對兩幅影象進行主觀比較,肉眼幾乎無法分辨出兩幅圖的區別。
down.yuv檔案轉換成功後,再增加了三個大小、情景不同測試檔案,驗證轉換程式的普遍適用性。下圖分別為bunny.yuv(640*360) 、highway.yuv (176*144)、flower.yuv(176*144)的對比結果。
實驗一 彩色空間轉換實驗 420YUV2RGB
1.實驗原理 由r,g,b轉換為y,u,v的公式是實現從y,u,v返回到r,g,b的基礎。其中經過了中間變數色差訊號r y,b y,公式如下 y 0.2990r 0.5870g 0.1140b r y 0.7010r 0.5870g 0.1140b b y 0.2990r 0.587g 0.8860...
資料壓縮實驗之彩色空間轉換
學會從計算和程式的角度分析問題通過完成本實驗,理解計算思維,即從問題出發,通過逐步分析和分解,把原問題轉化為可用程式方式解決的問題。在此過程中設計出乙個解決方案。進一步理解彩色空間的概念並掌握不同彩色空間轉換的基本方程。通過逐步設計程式,掌握程式設計細節 如查詢表的設計,記憶體分配,對 u 和 v ...
彩色空間轉換(修訂之後)
首先開闢乙個快取區。int w 256 int h 256 程式初始化 開啟兩個檔案 定義變數和緩衝區等 file rgbfile null file yuvfile null unsigned char r,g,b,pf,y,u,v,u,v 開啟rgb檔案 rgbfile fopen d dsx ...