工作中經常會使用一些顏色空間,最主要的就是使用RGB空間和YUV空間,把兩空間的一些知識記錄在此。
1. 什么是RGB?
RGB是紅綠藍三原色的意思,R=Red、G=Green、B=Blue。
2.什么是YUV/YCbCr/YPbPr?
亮度信號經常被稱作Y,色度信號是由兩個互相獨立的信號組成。視顏色系統和格式不同,兩種色度信號經常被稱作U和V或Pb和Pr或Cb和Cr。這些都是由不同的編碼格式所產生的,但是實際上,他們的概念基本相同。在DVD中,色度信號被存儲成Cb和Cr(C代表顏色,b代表藍色,r代表紅色)。
3.什么是4:4:4、4:2:2、4:2:0?
在 最近十年中,視頻工程師發現人眼對色度的敏感程度要低於對亮度的敏感程度。在生理學中,有一條規律,那就是人類視網膜上的視網膜桿細胞要多於視網膜錐細 胞,說得通俗一些,視網膜桿細胞的作用就是識別亮度,而視網膜錐細胞的作用就是識別色度。所以,你的眼睛對於亮和暗的分辨要比對顏色的分辨精細一些。正是 因為這個,在我們的視頻存儲中,沒有必要存儲全部顏色信號。既然眼睛看不見,那為什么要浪費存儲空間(或者說是金錢)來存儲它們呢?
像Beta或VHS之類的消費用錄像帶就得益於將錄像帶上的更多帶寬留給黑—白信號(被稱作“亮度”),將稍少的帶寬留給彩色信號(被稱作“色度”)。
在MPEG2(也就是DVD使用的壓縮格式)當中,Y、Cb、Cr信號是分開儲存的(這就是為什么分量視頻傳輸需要三條電纜)。其中Y信號是黑白信號,是以全分辨率存儲的。但是,由於人眼對於彩色信息的敏感度較低,色度信號並不是用全分辨率存儲的。
色度信號分辨率最高的格式是4:4:4,也就是說,每4點Y采樣,就有相對應的4點Cb和4點Cr。換句話說,在這種格式中,色度信號的分辨率和亮度信號的分辨率是相同的。這種格式主要應用在視頻處理設備內部,避免畫面質量在處理過程中降低。當圖像被存儲到Master Tape,比如D1或者D5,的時候,顏色信號通常被削減為4:2:2。
在圖中,你可以看到4:4:4格式的亮度、色度采樣分布。就像圖中所表示的,畫面中每個象素都有與之對應的色度和亮度采樣信息。
其次就是4:2:2,就是說,每4點Y采樣,就有2點Cb和2點Cr。在這種格式中,色度信號的掃描線數量和亮度信號一樣多,但是每條掃描線上的色度采樣點 數卻只有亮度信號的一半。當4:2:2信號被解碼的時候,“缺失”的色度采樣,通常由一定的內插補點算法通過它兩側的色度信息運算補充。
看4:2:2格式亮度、色度采樣的分布情況。在這里,每個象素都有與之對應的亮度采樣,同時一半的色度采樣被丟棄,所以我們看到,色度采樣信號每隔 一個采樣點才有一個。當着張畫面顯示的時候,缺少的色度信息會由兩側的顏色通過內插補點的方式運算得到。就像上面提到的那樣,人眼對色度的敏感程度不如亮 度,大多數人並不能分辨出4:2:2和4:4:4顏色構成的畫面之間的不同。
色度信號分辨率最低的格式,也就是DVD所使用的 格式,就是4:2:0了。事實上4:2:0是一個混亂的稱呼,按照字面上理解,4:2:0應該是每4點Y采樣,就有2點Cb和0點Cr,但事實上完全不是 這樣。事實上,4:2:0的意思是,色度采樣在每條橫向掃描線上只有亮度采樣的一半,掃描線的條數上,也只有亮度的一半!換句話說,無論是橫向還是縱向, 色度信號的分辨率都只有亮度信號的一半。舉個例子,如果整張畫面的尺寸是720*480,那么亮度信號是720*480,色度信號只有360*240。在 4:2:0中,“缺失”的色度采樣不單單要由左右相鄰的采樣通過內插補點計算補充,整行的色度采樣也要通過它上下兩行的色度采樣通過內插補點運算獲得。這 樣做的原因是為了最經濟有效地利用DVD的存儲空間。誠然,4:4:4的效果很棒,但是如果要用4:4:4存儲一部電影,我們的DVD盤的直徑至少要有兩 英尺(六十多厘米)!
上圖表示了概念上4:2:0顏色格式非交錯畫面中亮度、色度采樣信號的排列情況。同4:2:2格式 一樣,每條掃描線中,只有一半的色度采樣信息。與4:2:2不同的是,不光是橫向的色度信息被“扔掉”了一半,縱向的色度信息也被“扔掉”了一半,整個屏 幕中色度采樣只有亮度采樣的四分之一。請注意,在4:2:0顏色格式中,色度采樣被放在了兩條掃描線中間。為什么會這樣呢?很簡單:DVD盤上的顏色采樣 是由其上下兩條掃描線的顏色信息“平均”而來的。比如,圖三中,第一行顏色采樣(Line 1和Line 2中間夾着的那行)是由Line 1和Line 2“平均”得到的,第二行顏色采樣(Line 3和Line 4中間夾着的那行)也是同樣的道理,是由Line 3和Line 4得到的。
雖然文章中多次提到“平均”這個概念,但是這個“平均”可不是我們通常意義上的(a+B)/2的平均。顏色的處理有極其復雜的算法保證其最大限度地減少失真,接近原始質量。
關於 RGB 跟 YUV 的轉換:
計算機彩色顯示器顯示色彩的原理與彩色電視機一樣,都是采用R(Red)、G(Green)、B(Blue)相加混色的原理:通過發射出三種不同強度的電子束,使屏幕內側覆蓋的紅、綠、藍磷光材料發光而產生色彩。這種色彩的表示方法稱為RGB色彩空間表示(它也是多媒體計算機技術中用得最多的一種色彩空間表 示方法)。
根據三基色原理,任意一種色光F都可以用不同分量的R、G、B三色相加混合而成。
F = r [ R ] + g [ G ] + b [ B ]
其中,r、g、b分別為三基色參與混合的系數。當三基色分量都為0(最弱)時混合為黑色光;而當三基色分量都為k(最強)時混合為白色光。調整r、g、b三個系數的值,可以混合出介於黑色光和白色光之間的各種各樣的色光。
那 么YUV又從何而來呢?在現代彩色電視系統中,通常采用三管彩色攝像機或彩色CCD攝像機進行攝像,然后把攝得的彩色圖像信號經分色、分別放大校正后得到 RGB,再經過矩陣變換電路得到亮度信號Y和兩個色差信號R-Y(即U)、B-Y(即V),最后發送端將亮度和色差三個信號分別進行編碼,用同一信道發送 出去。這種色彩的表示方法就是所謂的YUV色彩空間表示。
采用YUV色彩空間的重要性是它的亮度信號Y和色度信號U、V是分離的。如果只有Y信號分量而沒有U、V分量,那么這樣表示的圖像就是黑白灰度圖像。彩色電視采用YUV空間正是為了用亮度信號Y解決彩色電視機與黑白電視機的兼容問題,使黑白電視機也能接收彩色電視信號。
YUV與RGB相互轉換的公式如下(RGB取值范圍均為0-255):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
PS:貼上兩個網上找到的sourcecode:
RGB->YUV
Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B − Y )
Cr = 0.713(R − Y )
代碼:
uint8_t COL_RgbToYuv(uint8_t R,uint8_t G,uint8_t B, uint8_t *y,int8_t *u,int8_t *v)
{
float rr=R,bb=B,gg=G;
float yy,uu,vv;
yy=0.299*rr+ 0.587*gg+ 0.114*bb;
uu=-0.169*rr+ -0.331*gg+ 0.5*bb;
vv=0.5*rr+ -0.419*gg+ -0.081*bb;
if(uu>127) uu=127;
if(uu-127) uu=-127;
*u=(int8_t)floor(uu);
if(vv>127) vv=127;
if(vv-127) vv=-127;
*v=(int8_t)floor(vv);
if(yy>255) yy=255;
if(yy0) yy=0;
*y=(uint8_t)floor(yy);
return 1;
}
YUV->RGB
R = Y + 1.402Cr
G = Y − 0.344Cb − 0.714Cr
B = Y + 1.772Cb
代碼:
uint8_t COL_YuvToRgb( uint8_t y,int8_t u,int8_t v,uint8_t *r,uint8_t *g,uint8_t *b)
{
float rr,bb,gg;
float yy=y,uu=u,vv=v;
rr= yy+ 1.402*vv;
gg= yy+ -0.344*uu+ -0.714*vv;
bb= yy+ 1.772*uu ;
#define CLIP(x) if(x>255) x=255; else if (x0) x=0;x=x+0.49;
#define CVT(x,y) CLIP(x);*y=(uint8_t)floor(x);
CVT(rr,r);
CVT(gg,g);
CVT(bb,b);
return 1;
}
YUV介紹
YUV的原理是把亮度與色度分離,研究證明,人眼對亮度的敏感超過色度。利用這個原理,可以把色度信息減少一點,人眼也無法查覺這一點。YUV三個字母中,其中”Y”表示明亮度(Lumina nce或Luma),也就是灰階值;而”U”和”V”表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定像素的顏色。用這個三個字母好象就是通道命令重點內容
使用YUV的優點有兩個:
1,彩色YUV圖像轉黑白YUV圖像轉換非常簡單,這一特性用在於電視信號上。
2,YUV是數據總尺寸小於RGB格式
RGB介紹
RGB色彩模式是工業界的一種顏色標准,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎包括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。
視頻像素
-視頻像素數據在視頻播放器的解碼流程中的位置如下圖所示
本文分別介紹如下幾個RGB/YUV視頻像素數據處理函數:
分離YUV444P像素數據中的Y、U、V分量
分離YUV444P像素數據中的Y、U、V分量
將YUV420P像素數據去掉顏色(變成灰度圖)
將YUV420P像素數據的亮度減半
代碼如下
(1) 分離YUV420P像素數據中的Y、U、V分量
本程序中的函數可以將YUV420P數據中的Y、U、V三個分量分離開來並保存成三個文件。函數的代碼如下所示。
/**
* Split Y, U, V planes in YUV420P file.
* @param url Location of Input YUV file.
* @param w Width of Input YUV file.
* @param h Height of Input YUV file.
* @param num Number of frames to process.
*
*/
int simplest_yuv420_split(char *url, int w, int h,int num){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_420_y.y","wb+");
FILE *fp2=fopen("output_420_u.y","wb+");
FILE *fp3=fopen("output_420_v.y","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3/2,fp);
//Y
fwrite(pic,1,w*h,fp1);
//U
fwrite(pic+w*h,1,w*h/4,fp2);
//V
fwrite(pic+w*h*5/4,1,w*h/4,fp3);
}
free(pic);
fclose(fp);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
調用上面函數的方法如下所示。
simplest_yuv420_split("lena_256x256_yuv420p.yuv",256,256,1);
從代碼可以看出,如果視頻幀的寬和高分別為w和h,那么一幀YUV420P像素數據一共占用w*h*3/2 Byte的數據。其中前w*h Byte存儲Y,接着的w*h*1/4 Byte存儲U,最后w*h*1/4 Byte存儲V。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件分離成為三個文件:
output_420_y.y:純Y數據,分辨率為256x256。
output_420_u.y:純U數據,分辨率為128x128。
output_420_v.y:純V數據,分辨率為128x128。
程序輸入的原圖如下所示。
lena_256x256_yuv420p.yuv
程序輸出的三個文件的截圖如下圖所示。在這里需要注意輸出的U、V分量在YUV播放器中也是當做Y分量進行播放的。
output_420_y.y
output_420_u.y
output_420_v.y
(2)分離YUV444P像素數據中的Y、U、V分量
本程序中的函數可以將YUV444P數據中的Y、U、V三個分量分離開來並保存成三個文件。函數的代碼如下所示。
/**
* Split Y, U, V planes in YUV444P file.
* @param url Location of YUV file.
* @param w Width of Input YUV file.
* @param h Height of Input YUV file.
* @param num Number of frames to process.
*
*/
int simplest_yuv444_split(char *url, int w, int h,int num){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_444_y.y","wb+");
FILE *fp2=fopen("output_444_u.y","wb+");
FILE *fp3=fopen("output_444_v.y","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3,fp);
//Y
fwrite(pic,1,w*h,fp1);
//U
fwrite(pic+w*h,1,w*h,fp2);
//V
fwrite(pic+w*h*2,1,w*h,fp3);
}
free(pic);
fclose(fp);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
調用上面函數的方法如下所示。
“`
simplest_yuv444_split(“lena_256x256_yuv444p.yuv”,256,256,1);
“`從代碼可以看出,如果視頻幀的寬和高分別為w和h,那么一幀YUV444P像素數據一共占用w*h*3 Byte的數據。其中前w*h Byte存儲Y,接着的w*h Byte存儲U,最后w*h Byte存儲V。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv444p.yuv的YUV444P格式的像素數據文件分離成為三個文件:
output_444_y.y:純Y數據,分辨率為256x256。
output_444_u.y:純U數據,分辨率為256x256。
output_444_v.y:純V數據,分辨率為256x256。
輸入的原圖如下所示。
輸出的三個文件的截圖如下圖所示。
output_444_y.y
output_444_u.y
output_444_v.y
(3) 將YUV420P像素數據去掉顏色(變成灰度圖)
本程序中的函數可以將YUV420P格式像素數據的彩色去掉,變成純粹的灰度圖。函數的代碼如下。
/**
* Convert YUV420P file to gray picture
* @param url Location of Input YUV file.
* @param w Width of Input YUV file.
* @param h Height of Input YUV file.
* @param num Number of frames to process.
*/
int simplest_yuv420_gray(char *url, int w, int h,int num){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_gray.yuv","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3/2,fp);
//Gray
memset(pic+w*h,128,w*h/2);
fwrite(pic,1,w*h*3/2,fp1);
}
free(pic);
fclose(fp);
fclose(fp1);
return 0;
}
調用上面函數的方法如下所示。
simplest_yuv420_gray("lena_256x256_yuv420p.yuv",256,256,1);
從代碼可以看出,如果想把YUV格式像素數據變成灰度圖像,只需要將U、V分量設置成128即可。這是因為U、V是圖像中的經過偏置處理的色度分量。色度分量在偏置處理前的取值范圍是-128至127,這時候的無色對應的是“0”值。經過偏置后色度分量取值變成了0至255,因而此時的無色對應的就是128了。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件處理成名稱為output_gray.yuv的YUV420P格式的像素數據文件。輸入的原圖如下所示。
處理后的圖像如下所示。
(4)將YUV420P像素數據的亮度減半
本程序中的函數可以通過將YUV數據中的亮度分量Y的數值減半的方法,降低圖像的亮度。函數代碼如下所示。
/**
* Halve Y value of YUV420P file
* @param url Location of Input YUV file.
* @param w Width of Input YUV file.
* @param h Height of Input YUV file.
* @param num Number of frames to process.
*/
int simplest_yuv420_halfy(char *url, int w, int h,int num){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_half.yuv","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3/2,fp);
//Half
for(int j=0;j<w*h;j++){
unsigned char temp=pic[j]/2;
//printf("%d,\n",temp);
pic[j]=temp;
}
fwrite(pic,1,w*h*3/2,fp1);
}
free(pic);
fclose(fp);
fclose(fp1);
return 0;
}
調用上面函數的方法如下所示。
simplest_yuv420_halfy("lena_256x256_yuv420p.yuv",256,256,1);
從代碼可以看出,如果打算將圖像的亮度減半,只要將圖像的每個像素的Y值取出來分別進行除以2的工作就可以了。圖像的每個Y值占用1 Byte,取值范圍是0至255,對應C語言中的unsigned char數據類型。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件處理成名稱為output_half.yuv的YUV420P格式的像素數據文件。輸入的原圖如下所示。
處理后的圖像如下所示。
---------------------
作者:yangyasong
來源:CSDN
原文:https://blog.csdn.net/yangyasong/article/details/80681135
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
YUV介紹 YUV的原理是把亮度與色度分離,研究證明,人眼對亮度的敏感超過色度。利用這個原理,可以把色度信息減少一點,人眼也無法查覺這一點。YUV三個字母中,其中”Y”表示明亮度(Lumina nce或Luma),也就是灰階值;而”U”和”V”表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定像素的顏色。用這個三個字母好象就是通道命令重點內容 使用YUV的優點有兩個: 1,彩色YUV圖像轉黑白YUV圖像轉換非常簡單,這一特性用在於電視信號上。 2,YUV是數據總尺寸小於RGB格式
RGB介紹 RGB色彩模式是工業界的一種顏色標准,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎包括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。
視頻像素 -視頻像素數據在視頻播放器的解碼流程中的位置如下圖所示
本文分別介紹如下幾個RGB/YUV視頻像素數據處理函數:
分離YUV444P像素數據中的Y、U、V分量分離YUV444P像素數據中的Y、U、V分量將YUV420P像素數據去掉顏色(變成灰度圖)將YUV420P像素數據的亮度減半代碼如下 (1) 分離YUV420P像素數據中的Y、U、V分量 本程序中的函數可以將YUV420P數據中的Y、U、V三個分量分離開來並保存成三個文件。函數的代碼如下所示。
/** * Split Y, U, V planes in YUV420P file. * @param url Location of Input YUV file. * @param w Width of Input YUV file. * @param h Height of Input YUV file. * @param num Number of frames to process. * */ int simplest_yuv420_split(char *url, int w, int h,int num){ FILE *fp=fopen(url,"rb+"); FILE *fp1=fopen("output_420_y.y","wb+"); FILE *fp2=fopen("output_420_u.y","wb+"); FILE *fp3=fopen("output_420_v.y","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3/2,fp); //Y fwrite(pic,1,w*h,fp1); //U fwrite(pic+w*h,1,w*h/4,fp2); //V fwrite(pic+w*h*5/4,1,w*h/4,fp3); }
free(pic); fclose(fp); fclose(fp1); fclose(fp2); fclose(fp3);
return 0; } 1234567891011121314151617181920212223242526272829303132333435調用上面函數的方法如下所示。
simplest_yuv420_split("lena_256x256_yuv420p.yuv",256,256,1); 12從代碼可以看出,如果視頻幀的寬和高分別為w和h,那么一幀YUV420P像素數據一共占用w*h*3/2 Byte的數據。其中前w*h Byte存儲Y,接着的w*h*1/4 Byte存儲U,最后w*h*1/4 Byte存儲V。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件分離成為三個文件:
output_420_y.y:純Y數據,分辨率為256x256。 output_420_u.y:純U數據,分辨率為128x128。 output_420_v.y:純V數據,分辨率為128x128。
程序輸入的原圖如下所示。
lena_256x256_yuv420p.yuv
程序輸出的三個文件的截圖如下圖所示。在這里需要注意輸出的U、V分量在YUV播放器中也是當做Y分量進行播放的。
output_420_y.y
output_420_u.y
output_420_v.y
(2)分離YUV444P像素數據中的Y、U、V分量
本程序中的函數可以將YUV444P數據中的Y、U、V三個分量分離開來並保存成三個文件。函數的代碼如下所示。
/** * Split Y, U, V planes in YUV444P file. * @param url Location of YUV file. * @param w Width of Input YUV file. * @param h Height of Input YUV file. * @param num Number of frames to process. * */ int simplest_yuv444_split(char *url, int w, int h,int num){ FILE *fp=fopen(url,"rb+"); FILE *fp1=fopen("output_444_y.y","wb+"); FILE *fp2=fopen("output_444_u.y","wb+"); FILE *fp3=fopen("output_444_v.y","wb+"); unsigned char *pic=(unsigned char *)malloc(w*h*3);
for(int i=0;i<num;i++){ fread(pic,1,w*h*3,fp); //Y fwrite(pic,1,w*h,fp1); //U fwrite(pic+w*h,1,w*h,fp2); //V fwrite(pic+w*h*2,1,w*h,fp3); }
free(pic); fclose(fp); fclose(fp1); fclose(fp2); fclose(fp3);
return 0; } 123456789101112131415161718192021222324252627282930313233調用上面函數的方法如下所示。
“` simplest_yuv444_split(“lena_256x256_yuv444p.yuv”,256,256,1);
“`從代碼可以看出,如果視頻幀的寬和高分別為w和h,那么一幀YUV444P像素數據一共占用w*h*3 Byte的數據。其中前w*h Byte存儲Y,接着的w*h Byte存儲U,最后w*h Byte存儲V。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv444p.yuv的YUV444P格式的像素數據文件分離成為三個文件: output_444_y.y:純Y數據,分辨率為256x256。 output_444_u.y:純U數據,分辨率為256x256。 output_444_v.y:純V數據,分辨率為256x256。 輸入的原圖如下所示。
輸出的三個文件的截圖如下圖所示。
output_444_y.y
output_444_u.y
output_444_v.y
(3) 將YUV420P像素數據去掉顏色(變成灰度圖)
本程序中的函數可以將YUV420P格式像素數據的彩色去掉,變成純粹的灰度圖。函數的代碼如下。
/** * Convert YUV420P file to gray picture * @param url Location of Input YUV file. * @param w Width of Input YUV file. * @param h Height of Input YUV file. * @param num Number of frames to process. */ int simplest_yuv420_gray(char *url, int w, int h,int num){ FILE *fp=fopen(url,"rb+"); FILE *fp1=fopen("output_gray.yuv","wb+"); unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){ fread(pic,1,w*h*3/2,fp); //Gray memset(pic+w*h,128,w*h/2); fwrite(pic,1,w*h*3/2,fp1); }
free(pic); fclose(fp); fclose(fp1); return 0; } 123456789101112131415161718192021222324調用上面函數的方法如下所示。
simplest_yuv420_gray("lena_256x256_yuv420p.yuv",256,256,1); 12從代碼可以看出,如果想把YUV格式像素數據變成灰度圖像,只需要將U、V分量設置成128即可。這是因為U、V是圖像中的經過偏置處理的色度分量。色度分量在偏置處理前的取值范圍是-128至127,這時候的無色對應的是“0”值。經過偏置后色度分量取值變成了0至255,因而此時的無色對應的就是128了。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件處理成名稱為output_gray.yuv的YUV420P格式的像素數據文件。輸入的原圖如下所示。
處理后的圖像如下所示。
(4)將YUV420P像素數據的亮度減半
本程序中的函數可以通過將YUV數據中的亮度分量Y的數值減半的方法,降低圖像的亮度。函數代碼如下所示。
/** * Halve Y value of YUV420P file * @param url Location of Input YUV file. * @param w Width of Input YUV file. * @param h Height of Input YUV file. * @param num Number of frames to process. */ int simplest_yuv420_halfy(char *url, int w, int h,int num){ FILE *fp=fopen(url,"rb+"); FILE *fp1=fopen("output_half.yuv","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){ fread(pic,1,w*h*3/2,fp); //Half for(int j=0;j<w*h;j++){ unsigned char temp=pic[j]/2; //printf("%d,\n",temp); pic[j]=temp; } fwrite(pic,1,w*h*3/2,fp1); }
free(pic); fclose(fp); fclose(fp1);
return 0; } 123456789101112131415161718192021222324252627282930調用上面函數的方法如下所示。
simplest_yuv420_halfy("lena_256x256_yuv420p.yuv",256,256,1); 12從代碼可以看出,如果打算將圖像的亮度減半,只要將圖像的每個像素的Y值取出來分別進行除以2的工作就可以了。圖像的每個Y值占用1 Byte,取值范圍是0至255,對應C語言中的unsigned char數據類型。上述調用函數的代碼運行后,將會把一張分辨率為256x256的名稱為lena_256x256_yuv420p.yuv的YUV420P格式的像素數據文件處理成名稱為output_half.yuv的YUV420P格式的像素數據文件。輸入的原圖如下所示。
處理后的圖像如下所示。
--------------------- 作者:yangyasong 來源:CSDN 原文:https://blog.csdn.net/yangyasong/article/details/80681135 版權聲明:本文為博主原創文章,轉載請附上博文鏈接!