實驗一 彩色空間轉換實驗 420YUV2RGB

2021-07-29 02:31:33 字數 4461 閱讀 6910

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

根據以上的公式計算出了怎樣由r,g,b轉到y,u,v。

(1)r,g,b到y,u,v

為了使r-y以及b-y的動態範圍不超過0.5,因此在其本身又乘了乙個係數來壓縮它的動態範圍,在數碼訊號中將此壓縮過幅度訊號稱為cb,cr:

cb=0.5640(b-y)

cr=0.7130(r-y)

為了方便起見就將它們記為u,v訊號

經過替換r-y,b-y,所以就有了以下的公式:

v=0.5000r-0.4187g-0.0813b

u=-0.1684r-0.3316g+0.5000b

為了使最終的數字處理過程避免對負數的計算,又對以上的公式附加了128的偏置電平,得到了以下的最終公式:

v=0.7130(r-y)+128

u=0.5640(b-y)+128

也就是v=0.5000r-0.4187g-0.0813b+128

u=-0.1684r-0.3316g+0.5000b+128

(2)y,u,u轉r,g,b

將上面的公式進行反變就會得到我們需要的公式,如下:

r=y+1.4025*(v-128)

g=y-0.7143*(v-128)-0.3443*(u-128)

b=y+1.7730*(u-128)

(3)取樣形式及資料的空間分配

對原始的資料r,g,b進行了4:2:0格式的取樣得到了相應的y,u,v資料,也就是y的資料量是沒有任何變化的而u,v的資料量則是y的1/4,

對應於y的水平以及垂直方向資料量都只有一半。

r,g,b到y,u,v進行了下取樣,每四個畫素為一組,形成的是2*2的方陣,其中y是每個畫素都有,根據r,g,b計算得來就可以而u,v是4個畫素只取乙個,

所以計算出的四個值要取最後的平均值,對於利用y,u,v還原成r,g,b的時候利用下取樣,由於u,v 的資料量不夠,則首先要將其還原成與y相同的資料量,

才能繼續下面的計算。

根據上面的分析可知為r,g,b分配的儲存空間總的就為寬*高*3,其中的3為3個位元組,每乙個位元組為8位元,每乙個位元組儲存乙個分量的資料,

則對應的y的儲存空間就為寬*高,u,v分別為寬*高*(1/4).

2.實驗流程分析

(1)首先讀入待轉換的檔名,資料的寬高和輸出檔案的檔名;

(2)在程式的開頭進行初始化,定義基本的變數以及為其賦值例如檔案資料的寬高,再就是利用malloc()函式為緩衝區開記憶體,buffer為無符號整型

(3)開啟兩個檔案,讀資料存到定義的y,u,vbuffer變數中,逐步計算的結果則存到rgb_buffer中

(4)將輸出的結果匯入到外部檔案中,利用yuv viewer進行檢視(注意影象的尺寸設定)

(5)程式編譯鏈結之後,除錯時要在工程選項中進行設定工作目錄和程式變數

3.實驗的主要**分析

標頭檔案的內容:

yuv2rgb.h

#ifndef yuv2rgb_h_

#define yuv2rgb_h_

int yuv2rgb(int x_dim,int y_dim,void *rgb_out,void *y_in,void *u_in,void *v_in);

void initlookuptable();

#endif

以上內容與rgb2yuv相比,僅僅是改變了yuv2rgb中的函式引數,原來的輸出則作為了新的輸入參與操作。

yuv2rgb.cpp

#include "stdlib.h"

#include "yuv2rgb.h"

static float yuvrgb14025[256];

static float yuvrgb07143[256], yuvrgb03443[256];

static float yuvrgb17730[256];

以上為標頭檔案以及一些要用到陣列的初始定義

函式yuv2rgb的實現:

(1)變數的定義

static int init_done = 0;

long i, j, size;

unsigned char *r, *g, *b,*rgb;

unsigned char *y, *u, *v,*up_u,up_v;

unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;

unsigned char *y_buffer, *u_buffer, *v_buffer,*rgb_buffer;

unsigned char *up_u_buf,*up_v_buf;

float r',g',b';

(2)開闢快取空間

rgb_buffer = (unsigned char *)rgb_out;

y_buf = (unsigned char *)y_in;

u_buf = (unsigned char *)u_in;

v_buf = (unsigned char *)v_in;

up_u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));

up_v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));

(3)對u,v實現上取樣

for (j = 0; j < y_dim/2; j ++)

}

(4)將yuv轉化成rgb,其中r',g',y'為中間變數用來判斷資料是否越界

for (j = 0; j < y_dim; j ++)

}

(5)最後是釋放快取區與查詢表函式實體
if(up_u_buffer != null)

if(up_v_buffer != null)

部分**略過了,查詢表函式與rgb2yuv部分的格式基本一樣,只是部分數字有所改變。

main.cpp

變數的定義與開記憶體緩衝區與上次一樣

檔案的讀取部分基本一樣,只是調換了檔名

while (fread(ybuf, 1, framewidth * frameheight, yuvfile)&&

fread(ubuf, 1, framewidth * frameheight/4, yuvfile)&&

fread(vbuf, 1, framewidth * frameheight/4, yuvfile))

else

}printf("\n%u %ux%u video frames written\n",

videoframeswritten, framewidth, frameheight);

/* cleanup */

if(rgbfile!=null) fclose(rgbfile);

if(yuvfile!=null) fclose(yuvfile);

if(rgbbuf!=null) free(rgbbuf);

if(ybuf!=null) free(ybuf);

if(ubuf!=null) free(ubuf);

if(vbuf!=null) free(vbuf);

return(0);

}

以上**實現了具體檔案的轉換以及緩衝區的釋放。

4.實驗結果

影象的左邊為原圖,右邊則為轉換後的影象以及最終的差值影象

5.實驗總結

(1)實驗過程中資料處理的原理以及資料儲存的具體結構要清楚;

(2)變數定義過程中定義它的目的和意義要理解;

(3)具體函式的應用格式,應用場景,所要完成的最終操作要清楚;

(4)在編寫**的過程中開闢的快取區最後一定要釋放;

(5)編譯鏈結執行的過程中注意細節,有利用查錯,執行程式的時候不要忽略了某些要經過的步驟。

實驗一 彩色空間轉換實驗

rgb計色系統是基於三基色原理的顏色計算系統,由紅光分量r 綠光分量g 藍光分量b可以混合出任意彩色光。在rgb檔案中,單個畫素的儲存形式為bgr順序。yuv色彩空間通過乙個亮度訊號y和兩個色差訊號u v來表示影象。yuv檔案通常是先儲存所有畫素的y分量,再儲存u分量 v分量。在4 2 0取樣格式中...

資料壓縮實驗之彩色空間轉換

學會從計算和程式的角度分析問題通過完成本實驗,理解計算思維,即從問題出發,通過逐步分析和分解,把原問題轉化為可用程式方式解決的問題。在此過程中設計出乙個解決方案。進一步理解彩色空間的概念並掌握不同彩色空間轉換的基本方程。通過逐步設計程式,掌握程式設計細節 如查詢表的設計,記憶體分配,對 u 和 v ...

作業系統 程序狀態轉換(實驗一)

sdibt 計科181 用陣列模擬的 我的 有些bug,望大家提出寶貴意見 include includeusing namespace std 就緒 執行 執行 就緒 時間片完 阻塞 等待 阻塞 就緒 struct pcb 程序結構體 t int sumrun 0 最多可以同時執行多少程序 int...