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