實驗一 彩色空間轉換實驗

2021-07-29 00:15:26 字數 4616 閱讀 4924

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 ...