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

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

生活随笔

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

编程问答

rgb2yuv

發(fā)布時(shí)間:2025/1/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 rgb2yuv 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.rgb2yuv422p

?

代碼的運(yùn)算速度取決于以下幾個(gè)方面

1、 算法本身的復(fù)雜度,比如MPEG比JPEG復(fù)雜,JPEG比BMP圖片的編碼復(fù)雜。

2、 CPU自身的速度和設(shè)計(jì)架構(gòu)

3、 CPU的總線帶寬

4、 您自己代碼的寫(xiě)法

將RGB格式的彩色圖像先轉(zhuǎn)換成YUV圖像。

圖像轉(zhuǎn)換的公式如下:

Y = 0.299 * R + 0.587 * G + 0.114 * B;

圖像尺寸640*480*24bit,RGB圖像已經(jīng)按照RGBRGB順序排列的格式,放在內(nèi)存里面了。

以下是輸入和輸出的定義:

#define XSIZE 640

#define YSIZE 480

#define IMGSIZE XSIZE * YSIZE

typedef struct RGB

{

unsigned char R;

unsigned char G;

unsigned char B;

}RGB;

struct RGB in[IMGSIZE]; //需要計(jì)算的原始數(shù)據(jù)

unsigned char out[IMGSIZE]; //計(jì)算后的結(jié)果

?

第一個(gè)優(yōu)化

優(yōu)化原則:圖像是一個(gè)2D數(shù)組,我用一個(gè)一維數(shù)組來(lái)存儲(chǔ)。編譯器處理一維數(shù)組的效率要高過(guò)二維數(shù)組。

?

先寫(xiě)一個(gè)代碼:

Y = 0.299 * R + 0.587 * G + 0.114 * B;

void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i++)

{

double r,g,b,y;

unsigned char yy;

r = in[i].r;

g = in[i].g;

b = in[i].b;

y = 0.299 * r + 0.587 * g + 0.114 * b;

yy = y;

out[i] = yy;

}

}

這大概是能想得出來(lái)的最簡(jiǎn)單的寫(xiě)法了,實(shí)在看不出有什么毛病,好了,編譯一下跑一跑吧。

第一次試跑

這個(gè)代碼分別用vc6.0和gcc編譯,生成2個(gè)版本,分別在pc上和我的embedded system上面跑。

速度多少?

在PC上,由于存在硬件浮點(diǎn)處理器,CPU頻率也夠高,計(jì)算速度為20秒。

我的embedded system,沒(méi)有以上2個(gè)優(yōu)勢(shì),浮點(diǎn)操作被編譯器分解成了整數(shù)運(yùn)算,運(yùn)算速度為120秒左右。

?

去掉浮點(diǎn)運(yùn)算

上面這個(gè)代碼還沒(méi)有跑,我已經(jīng)知道會(huì)很慢了,因?yàn)檫@其中有大量的浮點(diǎn)運(yùn)算。只要能不用浮點(diǎn)運(yùn)算,一定能快很多。

?

Y = 0.299 * R + 0.587 * G + 0.114 * B;

這個(gè)公式怎么能用定點(diǎn)的整數(shù)運(yùn)算替代呢?

0.299 * R可以如何化簡(jiǎn)?

Y = 0.299 * R + 0.587 * G + 0.114 * B;

Y = D + E + F;

D = 0.299 * R;

E = 0.587 * G;

F = 0.114 * B;

我們就先簡(jiǎn)化算式D吧!

RGB的取值范圍都是0~255,都是整數(shù),只是這個(gè)系數(shù)比較麻煩,不過(guò)這個(gè)系數(shù)可以表示為:0.299 = 299 / 1000;

所以 D = ( R * 299) / 1000;

Y = (R * 299 + G * 587 + B * 114) / 1000;

?

這一下,能快多少呢?

Embedded system上的速度為45秒;

PC上的速度為2秒;

0.299 * R可以如何化簡(jiǎn)

Y = 0.299 * R + 0.587 * G + 0.114 * B;

Y = (R * 299 + G * 587 + B * 114) / 1000;

這個(gè)式子好像還有點(diǎn)復(fù)雜,可以再砍掉一個(gè)除法運(yùn)算。

前面的算式D可以這樣寫(xiě):

0.299=299/1000=1224/4096

所以 D = (R * 1224) / 4096

Y=(R*1224)/4096+(G*2404)/4096+(B*467)/4096

再簡(jiǎn)化為:

Y=(R*1224+G*2404+B*467)/4096

這里的/4096除法,因?yàn)樗?的N次方,所以可以用移位操作替代,往右移位12bit就是把某個(gè)數(shù)除以4096了。

?

void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i++)

{

int r,g,b,y;

r = 1224 * in[i].r;

g = 2404 * in[i].g;

b = 467 * in[i].b;

y = r + g + b;

y = y >> 12; //這里去掉了除法運(yùn)算

out[i] = y;

}

}

這個(gè)代碼編譯后,又快了20%。

雖然快了不少,還是太慢了一些,20秒處理一幅圖像,地球人都不能接受。

?

仔細(xì)端詳一下這個(gè)式子!

Y = 0.299 * R + 0.587 * G + 0.114 * B;

Y=D+E+F;

D=0.299*R;

E=0.587*G;

F=0.114*B;

?

RGB的取值有文章可做,RGB的取值永遠(yuǎn)都大于等于0,小于等于255,我們能不能將D,E,F都預(yù)先計(jì)算好呢?然后用查表算法計(jì)算呢?

我們使用3個(gè)數(shù)組分別存放DEF的256種可能的取值,然后。。。

?

查表數(shù)組初始化

int D[256],F[256],E[256];

void table_init()

{

int i;

for(i=0;i<256;i++)

{

D[i]=i*1224;

D[i]=D[i]>>12;

E[i]=i*2404;

E[i]=E[i]>>12;

F[i]=i*467;

F[i]=F[i]>>12;

}

}

void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i++)

{

int r,g,b,y;

r = D[in[i].r];//查表

g = E[in[i].g];

b = F[in[i].b];

y = r + g + b;

out[i] = y;

}

}

?

這一次的成績(jī)把我嚇出一身冷汗,執(zhí)行時(shí)間居然從30秒一下提高到了2秒!在PC上測(cè)試這段代碼,眼皮還沒(méi)眨一下,代碼就執(zhí)行完了。一下提高15倍,爽不爽?

繼續(xù)優(yōu)化
很多embedded system的32bit CPU,都至少有2個(gè)ALU,能不能讓2個(gè)ALU都跑起來(lái)?

?

void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i += 2) //一次并行處理2個(gè)數(shù)據(jù)

{

int r,g,b,y,r1,g1,b1,y1;

r = D[in[i].r];//查表 //這里給第一個(gè)ALU執(zhí)行

g = E[in[i].g];

b = F[in[i].b];

y = r + g + b;

out[i] = y;

r1 = D[in[i + 1].r];//查表 //這里給第二個(gè)ALU執(zhí)行

g1 = E[in[i + 1].g];

b1 = F[in[i + 1].b];

y = r1 + g1 + b1;

out[i + 1] = y;

}

}

2個(gè)ALU處理的數(shù)據(jù)不能有數(shù)據(jù)依賴,也就是說(shuō):某個(gè)ALU的輸入條件不能是別的ALU的輸出,這樣才可以并行。

這次成績(jī)是1秒。

?

查看這個(gè)代碼

int D[256],F[256],E[256]; //查表數(shù)組

void table_init()

{

int i;

for(i=0;i<256;i++)

{

D[i]=i*1224;

D[i]=D[i]>>12;

E[i]=i*2404;

E[i]=E[i]>>12;

F[i]=i*467;

F[i]=F[i]>>12;

}

}

到這里,似乎已經(jīng)足夠快了,但是我們反復(fù)實(shí)驗(yàn),發(fā)現(xiàn),還有辦法再快!

可以將int D[256],F[256],E[256]; //查表數(shù)組

更改為

unsigned short D[256],F[256],E[256]; //查表數(shù)組

?

這是因?yàn)榫幾g器處理int類型和處理unsigned short類型的效率不一樣。

再改動(dòng)

inline void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i += 2) //一次并行處理2個(gè)數(shù)據(jù)

{

int r,g,b,y,r1,g1,b1,y1;

r = D[in[i].r];//查表 //這里給第一個(gè)ALU執(zhí)行

g = E[in[i].g];

b = F[in[i].b];

y = r + g + b;

out[i] = y;

r1 = D[in[i + 1].r];//查表 //這里給第二個(gè)ALU執(zhí)行

g1 = E[in[i + 1].g];

b1 = F[in[i + 1].b];

y = r1 + g1 + b1;

out[i + 1] = y;

}

}

將函數(shù)聲明為inline,這樣編譯器就會(huì)將其嵌入到母函數(shù)中,可以減少CPU調(diào)用子函數(shù)所產(chǎn)生的開(kāi)銷(xiāo)。

這次速度:0.5秒。

?

其實(shí),我們還可以飛出地球的!

如果加上以下措施,應(yīng)該還可以更快:

1、 把查表的數(shù)據(jù)放置在CPU的高速數(shù)據(jù)CACHE里面;

2、 把函數(shù)calc_lum()用匯編語(yǔ)言來(lái)寫(xiě)

?

其實(shí),CPU的潛力是很大的

1、 不要抱怨你的CPU,記住一句話:“只要功率足夠,磚頭都能飛!”

2、 同樣的需求,寫(xiě)法不一樣,速度可以從120秒變化為0.5秒,說(shuō)明CPU的潛能是很大的!看你如何去挖掘。

3、 我想:要是Microsoft的工程師都像我這樣優(yōu)化代碼,我大概就可以用489跑windows XP了!

?

以上就是對(duì)《讓你的軟件飛起來(lái)》的摘錄,下面,我將按照這位牛人的介紹,對(duì)RGB到Y(jié)CbCr的轉(zhuǎn)換算法做以總結(jié)。

?

Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

?

?

#deinfe SIZE 256

#define XSIZE 640

#define YSIZE 480

#define IMGSIZE XSIZE * YSIZE

typedef struct RGB

{

unsigned char r;

unsigned char g;

unsigned char b;

}RGB;

struct RGB in[IMGSIZE]; //需要計(jì)算的原始數(shù)據(jù)

unsigned char out[IMGSIZE * 3]; //計(jì)算后的結(jié)果

?

unsigned short Y_R[SIZE],Y_G[SIZE],Y_B[SIZE],U_R[SIZE],U_G[SIZE],U_B[SIZE],V_R[SIZE],V_G[SIZE],V_B[SIZE]; //查表數(shù)組

void table_init()

{

int i;

for(i = 0; i < SIZE; i++)

{

Y_R[i] = (i * 1224) >> 12; //Y對(duì)應(yīng)的查表數(shù)組

Y_G[i] = (i * 2404) >> 12;

Y_B[i] = (i * 467) >> 12;

U_R[i] = (i * 602) >> 12; //U對(duì)應(yīng)的查表數(shù)組

U_G[i] = (i * 1183) >> 12;

U_B[i] = (i * 1785) >> 12;

V_R[i] = (i * 2519) >> 12; //V對(duì)應(yīng)的查表數(shù)組

V_G[i] = (i * 2109) >> 12;

V_B[i] = (i * 409) >> 12;

}

}

?

inline void calc_lum()

{

int i;

for(i = 0; i < IMGSIZE; i += 2) //一次并行處理2個(gè)數(shù)據(jù)

{

out[i] = Y_R[in[i].r] + Y_G[in[i].g] + Y_B[in[i].b]; //Y

out[i + IMGSIZE] = U_B[in[i].b] - U_R[in[i].r] - U_G[in[i].g]; //U

out[i + 2 * IMGSIZE] = V_R[in[i].r] - V_G[in[i].g] - V_B[in[i].b]; //V

?

out[i + 1] = Y_R[in[i + 1].r] + Y_G[in[i + 1].g] + Y_B[in[i + 1].b]; //Y

out[i + 1 + IMGSIZE] = U_B[in[i + 1].b] - U_R[in[i + 1].r] - U_G[in[i + 1].g]; //U

out[i + 1 + 2 * IMGSIZE] = V_R[in[i + 1].r] - V_G[in[i + 1].g] - V_B[in[i + 1].b]; //V

}

}

?

從公式中,我們關(guān)鍵要理解的一點(diǎn)是,UV / CbCr信號(hào)實(shí)際上就是藍(lán)色差信號(hào)和紅色差信號(hào),進(jìn)而言之,實(shí)際上一定程度上間接的代表了藍(lán)色和紅色的強(qiáng)度,理解這一點(diǎn)對(duì)于我們理解各種顏色變換處理的過(guò)程會(huì)有很大的幫助。

??????? 我們?cè)跀?shù)字電子多媒體領(lǐng)域所談到的YUV格式,實(shí)際上準(zhǔn)確的說(shuō),是以YcrCb色彩空間模型為基礎(chǔ)的具有多種存儲(chǔ)格式的一類顏色模型的家族(包括 YUV444 / YUV422 / YUV420 / YUV420P等等)。并不是傳統(tǒng)意義上用于PAL制模擬電視的YUV模型。這些YUV模型的區(qū)別主要在于UV數(shù)據(jù)的采樣方式和存儲(chǔ)方式,這里就不詳述。

??????? 而在Camera Sensor中,最常用的YUV模型是 YUV422格式,因?yàn)樗捎?個(gè)字節(jié)描述兩個(gè)像素,能和RGB565模型比較好的兼容。有利于Camera Sensor和Camera controller的軟硬件接口設(shè)計(jì)。

?

http://blog.csdn.net/frankiewang008/article/details/6854616

?

?

http://hi.baidu.com/zymill/item/b09445aa563d02796cd4558b

http://wenku.baidu.com/link?url=j97XMVF-UMfdNgt8c4KM3J1lUe0beWdno23c10MJzS8AEImRtJTBo7ZHj2Zx6GAwwYNKAbN0pDNs_Nd_McNCaIK00NiQUTSZypxVHqfc5KO百度文庫(kù)位圖信息

總結(jié)

以上是生活随笔為你收集整理的rgb2yuv的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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