织梦CMS - 轻松建站从此开始!

罗索

如何将BGR转成YUV420

jackyhwei 发布于 2011-04-29 11:09 点击:次 
写了一个程序可以把openCV的BGR图像格式转换成YUV4:2:0,然后通 过FFmpeg的API把YUV4:2:0的图像编码压缩,最后利用live555把压缩后的buffer打包成RTP包,最后用Unicast将它们发 送出去。简单的说就是 BGR—>YUV4:2:0—>encode to buffer—>RTP—>Unicast这样的过程。
TAG:

今天心情非常之好,花了一个下午时间搞定了困扰了我一个月的事情。写了一个程序可以把openCV的BGR图像格式转换成YUV4:2:0,然后通 过FFmpeg的API把YUV4:2:0的图像编码压缩,最后利用live555把压缩后的buffer打包成RTP包,最后用Unicast将它们发 送出去。简单的说就是 BGR—>YUV4:2:0—>encode to buffer—>RTP—>Unicast这样的过程。

把预想的程序完成真是一大快事,随便记录一部分比较特别的东西,因为openCV没有BGR转YUV420的函数,所以需要自己写一个,我 写的这个函数读入一个三通道的图像数据,然后先使用cvCvtColor函数,将BGR转成YCrCb,这个YCrCb是4:4:4也就是全抽样,然后对 Cb和Cr分量进行抽样,最后我们可以得到三个数组,分别存Y, U, V三个分量。这个转换不算复杂,就是使用了以下的概念。

YUV4:2:0

thumb.php

4:2:0并不意味着只有Y,Cb而没有Cr分量。它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。相邻的扫描行存储不同的色度分量, 也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0…以此类推。对每个色度分量来说,水平方向和竖直方向的抽样率都是 2:1,所以可以说色度的抽样率是4:1。对非压缩的8比特量化的视频来说,每个由2×2个2行2列相邻的像素组成的宏像素需要占用6字节内存。
八个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3][Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的码流为:Y0 U0 Y1 Y2 U2 Y3 Y5 V5 Y6 Y7 V7 Y8
射 出的像素点为:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7][Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7](来自百度百科)我们可以对每八个像素:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3][Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]进行一次抽样,抽样: Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 给Y分量,U0 U2 给U分量,V5 V7给V分量。

现在提供另一个简单的转换函数:

  1. void convertBGR2YUV420(IplImage *in, unsigned char* out_y
  2. , unsigned char* out_u, unsigned char* out_v)  
  3. {  
  4.     // first, convert the input image into YCbCr 
  5.     IplImage *tmp = cvCreateImage(cvSize(in->width, in->height), 8, 3); 
  6.     cvCvtColor(in, tmp, CV_RGB2YCrCb); 
  7. /*  
  8. * widthStep = channel number * width  
  9. * if width%4 == 0  
  10. * for example, width = 352, width%4 == 0, widthStep = 3 * 352 = 1056  
  11. */ 
  12.     int idx_in = 0;  
  13.     int idx_out = 0;  
  14.     int idx_out_y = 0;  
  15.     int idx_out_u = 0;  
  16.     int idx_out_v = 0; 
  17.     
  18.     for(int j = 0; j < in->height; j+=1) { 
  19.         idx_in = j * in->widthStep; 
  20.     
  21.         for(int i = 0; i < in->widthStep; i+=12) { 
  22.         // We use the chroma sample here, and put it into the out buffer 
  23.         // take the luminance sample 
  24.         out_y[idx_out_y] = tmp->imageData[idx_in + i + 0]; // Y 
  25.         idx_out_y++; 
  26.         out_y[idx_out_y] = tmp->imageData[idx_in + i + 3]; // Y 
  27.         idx_out_y++; 
  28.         out_y[idx_out_y] = tmp->imageData[idx_in + i + 6]; // Y 
  29.         idx_out_y++; 
  30.         out_y[idx_out_y] = tmp->imageData[idx_in + i + 9]; // Y 
  31.         idx_out_y++; 
  32.         if((j % 2) == 0) { 
  33. // take the blue-difference and red-difference chroma components sample  
  34. out_u[idx_out_u++] = tmp->imageData[idx_in + i + 1]; // Cr U  
  35. out_u[idx_out_u++] = tmp->imageData[idx_in + i + 7]; // Cr U  
  36. out_v[idx_out_v++] = tmp->imageData[idx_in + i + 2]; // Cb V  
  37. out_v[idx_out_v++] = tmp->imageData[idx_in + i + 8]; // Cb V 
  38.          }  
  39.       }    
  40.    }  
  41.    cvReleaseImage(&tmp); 

(hanyionet)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201102/10948.html]
本文出处:hanyionet.wordpress.com 作者:hanyionet
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容