日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

实验一:彩色空间转换(YUV2RGB)

發(fā)布時(shí)間:2024/3/13 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实验一:彩色空间转换(YUV2RGB) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
實(shí)驗(yàn)一:彩色空間轉(zhuǎn)換

#ifndef/#define/#endif?使用詳解:http://blog.csdn.net/abc5382334/article/details/18052757

Debug與Release版本的區(qū)別詳解:http://blog.csdn.net/ithzhang/article/details/7575483#comments

VS中Release和Debug模式的區(qū)別:http://blog.csdn.net/eric491179912/article/details/6154375

YUV格式分析:http://www.cnblogs.com/armlinux/archive/2012/02/15/2396763.html

一、實(shí)驗(yàn)基本原理

1.????彩色空間轉(zhuǎn)換的基本思想及轉(zhuǎn)換公式

(1)???YUVRGB空間的相互轉(zhuǎn)換

RGB格式轉(zhuǎn)YUV格式:

由電視原理知識(shí),

Y = 0.2990 R + 0.5870 G + 0.1140 B

R-Y=0.7010 R - 0.5870 G - 0.1140 B

B-Y=-0.2990 R-0.5870 G + 0.8860 B

為了使色差信號(hào)的動(dòng)態(tài)范圍控制在-0.50.5之間,需要進(jìn)行歸一化,對(duì)色差信號(hào)引入壓縮系數(shù),歸一化后的色差信號(hào)為:

U = - 0.1684 R - 0.3316 G + 0.5 B

V = 0.5 R - 0.4187 G - 0.0813 B

(2)???碼電平分配及數(shù)字表達(dá)式

亮電平信號(hào):在對(duì)分量信號(hào)進(jìn)行8比特均勻量化時(shí),共分為256個(gè)等間隔的量化級(jí)。為了防止信號(hào)變動(dòng)造成過(guò)載,在256級(jí)上端留20級(jí),下端留16級(jí)作為信號(hào)超越動(dòng)態(tài)范圍的保護(hù)帶。

色差信號(hào):量化后碼電平分配色差信號(hào)經(jīng)過(guò)歸一化處理后,動(dòng)態(tài)范圍為-0.50.5,讓色差零電平對(duì)應(yīng)碼電平128,色差信號(hào)總共占225個(gè)量化級(jí)。在256級(jí)上端留15級(jí),下端留16級(jí)作為信號(hào)超越動(dòng)態(tài)范圍的保護(hù)帶。

由此可知,YUV轉(zhuǎn)RGB公式為:

??????????????????????????R = Y + 1.4075 *V-128

G = Y 0.3455 *U128) – 0.7169 *V128

B = Y + 1.779 *U128

(3)???色度格式

4:2:0格式:色差信號(hào)UV的取樣頻率為亮度信號(hào)取樣頻率的四分之一,在水平方向和垂直方向上的取樣點(diǎn)數(shù)均為Y的一半。

所以:

RGB轉(zhuǎn)換YUV格式時(shí),根據(jù)公式計(jì)算得到一幀YUV數(shù)據(jù)后,要對(duì)色差信號(hào)UV進(jìn)行下采樣。

YUV轉(zhuǎn)換RGB格式時(shí),在利用公式進(jìn)行計(jì)算之前首先要對(duì)色差信號(hào)UV進(jìn)行上采樣。(下面是兩張丑丑的圖示~)




?

二、實(shí)驗(yàn)流程

1.????建立工程,C相關(guān)知識(shí)回顧(養(yǎng)成良好代碼書寫習(xí)慣)

1)?????程序文件一般分為三部分:

(1)頭文件:包括與結(jié)構(gòu)(類)的聲明和使用這些結(jié)構(gòu)(類)的函數(shù)的原型,不要將函數(shù)的定義或變量的聲明放在頭文件中,#ifndef/#define/#endif?防止頭文件被多次引用,詳解見(jiàn)文章頭部鏈接。

(2)源代碼文件:包含與結(jié)構(gòu)(類)有關(guān)的函數(shù)的代碼,即函數(shù)的定義

(3)源代碼文件(main.c/cpp):包含調(diào)用這些函數(shù)的代碼

2)?????學(xué)會(huì)使用帶參主函數(shù)定義以及命令參數(shù)、可執(zhí)行文件工作路徑的設(shè)置

VS2013步驟為:項(xiàng)目項(xiàng)目屬性配置屬性調(diào)試命令參數(shù)(編輯)/工作目錄(編輯:絕對(duì)路徑/瀏覽:找到具體文件夾目錄)如下圖:


??????

??????? 關(guān)于參數(shù)設(shè)置過(guò)程中DebugRelease版本的區(qū)別詳解鏈接見(jiàn)文章頭部鏈接。


2.????調(diào)試RGB轉(zhuǎn)換YUV程序

理解課上所給例程,尤其對(duì)色差信號(hào)進(jìn)行4:2:0下采樣部分,妙用指針可以很容易實(shí)現(xiàn),在課程作業(yè)編寫YUV轉(zhuǎn)換RGB程序中對(duì)UV數(shù)據(jù)進(jìn)行上采樣也是借鑒了例程的指針用法。

3.????編寫YUV轉(zhuǎn)換RGB程序,具體見(jiàn)下一部分。

三、關(guān)鍵代碼

#include "stdlib.h" #include "yuv2rgb.h" /*YUV->RGB 轉(zhuǎn)換公式 R = Y + 1.4075 *(V-128) G = Y – 0.3455 *(U –128) – 0.7169 *(V –128) B = Y + 1.779 *(U – 128) */ static float YUV2RGB14075[256]; static float YUV2RGB03455[256], YUV2RGB07169[256]; static float YUV2RGB1779[256];/************************************************************************ * * int YUV2RGB (int x_dim, int y_dim, void *ychunk, void *uchunk, void *vchunk, void *rgb_out, int flip) * * Purpose : It takes a YUV (4:2:0) format and convert it into * a 24-bit RGB bitmap. * * Input : x_dim the x dimension of the bitmap * y_dim the y dimension of the bitmap* * yuv chunk pointer to the YUV structurergb_out pointer to the buffer of the bitmap * * Output : 0 OK * 1 wrong dimension * 2 memory allocation error * * Side Effect : * None * * Date : 03/11/2017 * ************************************************************************/int YUV2RGB(int x_dim, int y_dim, void *ychunk, void *uchunk, void *vchunk, void *rgb_out, int flip) { static int init_done = 0;long i, j, size;unsigned char *r, *g, *b;unsigned char *y, *u, *v;unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv; unsigned char *addu_buffer, *addv_buffer;unsigned char *addu_buf, *addv_buf;if (init_done == 0){InitLookupTable();init_done = 1;}// check to see if x_dim and y_dim are divisible by 2if ((x_dim % 2) || (y_dim % 2)) return 1;size = x_dim * y_dim;// allocate memory addu_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));addv_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));b = (unsigned char *)rgb_out;y = (unsigned char *)ychunk; u = (unsigned char*)uchunk;v = (unsigned char*)vchunk;addu_buf = (unsigned char *)addu_buffer;addv_buf = (unsigned char *)addv_buffer;// 對(duì)UV塊進(jìn)行上采樣for (j = 0; j < y_dim/2; j++){psu = u + j * x_dim / 2;//原始數(shù)據(jù)U塊指針psv = v + j * x_dim / 2;//原始數(shù)據(jù)V塊指針pu1 = addu_buf + 2 * j * x_dim; //U塊奇數(shù)行首地址pu2 = addu_buf + (2 * j + 1) * x_dim;//U塊偶數(shù)行首地址pv1 = addv_buf + 2 * j * x_dim; //V塊奇數(shù)行首地址pv2 = addv_buf + (2 * j + 1) * x_dim;//V塊偶數(shù)行首地址for (i = 0; i < x_dim/2; i++){*pu1 = *psu;*pu2 = *psu;pu1++;pu2++;*pu1 = *psu;*pu2 = *psu; //U塊上采樣:“以1作4”*pv1 = *psv;*pv2 = *psv; pv1++;pv2++; *pv1 = *psv;*pv2 = *psv; //V塊上采樣:“以1作4”pu1++;pu2++;pv1++;pv2++;psu++;psv++; }} // convert YUV to RGBif (!flip) {for (j = 0; j < y_dim; j++){y = y + (y_dim - j - 1) * x_dim;addu_buf = addu_buf + (y_dim - j - 1) * x_dim;addv_buf = addv_buf + (y_dim - j - 1) * x_dim;for (i = 0; i < x_dim; i++) {g = b + 1;r = b + 2;adjust(b, g, r, y, addu_buf, addv_buf);b += 3;y++;addu_buf++;addv_buf++;}}}else { for (i = 0; i < size; i++){g = b + 1;r = b + 2;adjust(b, g, r, y, addu_buf, addv_buf);//對(duì)變量范圍作適應(yīng)性調(diào)整b += 3;y++;addu_buf++;addv_buf++;}}free(addu_buffer);free(addv_buffer);return 0; } void InitLookupTable() {int i;for (i = 16; i < 240; i++) YUV2RGB14075[i] = (float)1.4075 * (i-128);for (i = 16; i < 240; i++) YUV2RGB03455[i] = (float)0.3455 * (i - 128);for (i = 16; i < 240; i++) YUV2RGB07169[i] = (float)0.7169 * (i - 128);//for (i = 16; i < 240; i++) YUV2RGB1779[i] = (float)1.779 * (i-128); } void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char *v) {float temp = 0;temp = (float)(*y + YUV2RGB1779[*u]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*b = (unsigned char)temp;temp = (float)(*y - YUV2RGB03455[*u] - YUV2RGB07169[*v]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*g = (unsigned char)temp;temp = (float)(*y + YUV2RGB14075[*v]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*r = (unsigned char)temp; }

四、程序分析

RGB格式裸數(shù)據(jù)部分,三通道的排列順序依次是B\G\R,所以一個(gè)像素點(diǎn)有三個(gè)分別表示顏色的數(shù)據(jù)。

?YUV格式通常有兩大類:

打包(packed)格式:將YUV分量存放在同一個(gè)數(shù)組中,通常是幾個(gè)相鄰的像素組成一個(gè)宏像素(macro-pixel);

平面(planar)格式:使用三個(gè)數(shù)組分開(kāi)存放YUV三個(gè)分量,就像是一個(gè)三維平面一樣。

下面是我們測(cè)試所用RGBYUV文件的兩張丑丑的排列簡(jiǎn)示圖~

依次是B G R B G R.........

每幀數(shù)據(jù)Y U V分塊排列......


程序?qū)崿F(xiàn)過(guò)程:

1.? 主程序?qū)崿F(xiàn)對(duì)YUV視頻逐幀讀取數(shù)據(jù)分別處理,根據(jù)格式特點(diǎn),開(kāi)辟三個(gè)緩存分別存放YUV三個(gè)分量各自的數(shù)據(jù)。

2.? 關(guān)鍵函數(shù)首先對(duì)U\V色差信號(hào)作上采樣,下采樣過(guò)程中相鄰四個(gè)數(shù)據(jù)取平均得到一個(gè)U/V,所以上采樣我們這里相應(yīng)地就可以->以1代4。

3.? 接著就是帶入公式計(jì)算,依然使用查找表的方法,重點(diǎn)注意強(qiáng)制類型轉(zhuǎn)換過(guò)程,在void adjust(~~~)函數(shù)中實(shí)現(xiàn),超出0~255范圍內(nèi)的rgb值, 負(fù)數(shù)取0,大于255的取255。

4.? 最后按照存儲(chǔ)格式寫入文件。

五、實(shí)驗(yàn)結(jié)果

(所有YUV測(cè)試文件均來(lái)自網(wǎng)站:http://trace.eas.asu.edu/yuv/index.html)

1.? 如何檢驗(yàn)程序結(jié)果是否正確:

由于RGB的裸數(shù)據(jù)并不構(gòu)成文件格式,所以我們的YUV視頻通過(guò)程序轉(zhuǎn)換成RGB文件以后,再用RGB2YUV程序轉(zhuǎn)換成YUV格式文件,用YUV播放 器查看,對(duì)比前后兩個(gè)視頻圖像畫面,若有明顯色調(diào)失真或不明色塊之類則表明程序出錯(cuò)。

2.? 下面是這次實(shí)驗(yàn)程序編寫過(guò)程中出現(xiàn)的錯(cuò)誤整理:

①程序結(jié)果出錯(cuò):

測(cè)試得到上圖結(jié)果時(shí),首先注意到明顯的藍(lán)紅色塊,猜測(cè)是公式計(jì)算過(guò)程中強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤,老師上課也提醒過(guò),查閱相關(guān)書籍得到C語(yǔ)言各種數(shù)據(jù)類型大小范圍如下圖:

改正: 將公式計(jì)算和強(qiáng)制類型轉(zhuǎn)換過(guò)程另寫函數(shù),將計(jì)算所得結(jié)果在unsignedchar類型 0~255范圍之外的再次處理。

②程序運(yùn)行報(bào)錯(cuò):program received signal SIGSEGV,Segmentationfault.

通過(guò)相關(guān)搜索以及不斷改正調(diào)試發(fā)現(xiàn),出現(xiàn)這種錯(cuò)誤的原因是因?yàn)槁暶髦羔樅鬀](méi)有初始化,指針指向地址為未知,未初始化指針直接執(zhí)行運(yùn)算就會(huì)出錯(cuò)。

改正:程序中聲明的指針初始化。

③程序本身錯(cuò)誤:對(duì)比差錯(cuò)圖像與原圖像具體差異:

??????? 下面是一組結(jié)果圖:

藍(lán)紅色塊錯(cuò)誤處理完之后,得到的圖像還是不對(duì),但對(duì)于錯(cuò)誤原因不是很清楚,于是再次進(jìn)行各種測(cè)試。

看上去好像是色調(diào)改變了

繼續(xù)測(cè)試


。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

還好找到了這個(gè)顏色豐富亮麗的YUV,幫了大忙

似曾相識(shí)的豎條色彩分界

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

所以這應(yīng)該是發(fā)生了某部分?jǐn)?shù)據(jù)的位置偏移,問(wèn)題應(yīng)該出現(xiàn)在有關(guān)數(shù)據(jù)計(jì)算部分。

??????? 于是重新查看程序,在直接得到數(shù)據(jù)的計(jì)算過(guò)程和U/V色差信號(hào)的上采樣兩部分仔細(xì)排查,最終發(fā)現(xiàn)錯(cuò)誤出現(xiàn)采樣程序部分的指針使用。

??????? 錯(cuò)誤:程序中指針psu\psv多進(jìn)行了一次偏移超出數(shù)據(jù)范圍。

上采樣部分正確代碼已經(jīng)在上面程序部分給出,指針使用圖示如下:

指針簡(jiǎn)圖(V同理):

以上錯(cuò)誤改正以后再次進(jìn)行多次測(cè)試,結(jié)果表明程序運(yùn)行結(jié)果正確。

test 1----


test 2----


test 3----

五、結(jié)論

掌握指針運(yùn)算很重要,會(huì)使程序變的簡(jiǎn)單。




tips/2017/04/30:對(duì)于人眼來(lái)說(shuō),亮度信號(hào)是最敏感的,如果將彩色圖像轉(zhuǎn)換為灰度圖像,僅僅需要轉(zhuǎn)換保存亮度信號(hào)就可以。

?

YUV官方播放器的注冊(cè)方法:

官方提供注冊(cè)碼:

REGEDIT4

?

[HKEY_CURRENT_USER\Software\tihohod.com\YUVPlayer\RegistrationInfo]

"RegistrationName"="Peace on Earth -Goodwill to Men"

"RegistrationKey"="JxsQHEseR43VXvp6kCV8w5ACtqNVJ11LhOAE4Pztk+Ksw211wohNjsR78XHoGajwlqIOU6gVz0zipwkJCfdvIqyAJrEgJLYB+NKwPGaD+OqbJD+oe+5xixyIKc7tT0ecQjNER47sA3HsUUhRl3LmKozxS2nH233WNPpJwoF4rL1Bjm5OfcM/jiixF/By85wQTdzSwAehjfvB7iO9tCaI9A=="

把上面key的內(nèi)容復(fù)制到一個(gè)編輯器,另存為key.reg,點(diǎn)擊運(yùn)行這個(gè)文件會(huì)自動(dòng)注冊(cè),就OK了





總結(jié)

以上是生活随笔為你收集整理的实验一:彩色空间转换(YUV2RGB)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。