之前在工作中使用V4L2 + Qt显示摄像头画面的时候,遇到的一个问题就是:摄像头通过V4L2采集到的数据只支持YUV格式的,但是Qt显示图片的时候需要RGB格式,所以需要一个转换函数。但是网上找的YUV转RGB函数在我的代码里面一跑就段错误了,程序coredown。

后来实在无奈,自己阅读了一下V4L2的官方文档,才发现自己太心急:只想找现成的代码去用,而没有理解底层的YUV数据的格式。其实,YUV数据的格式有很多种,不能一概而论,我自己的摄像头采集的数据格式和网上的代码对应的格式不一样就会导致转码出错。

我们可以看一下linux下/usr/include/linux/videodev2.h中有关yuv格式的宏:

/* Luminance+Chrominance formats */
#define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
#define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16  YUV 4:2:2     */
#define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
#define V4L2_PIX_FMT_UYVY    v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16  YUV 4:2:2     */
#define V4L2_PIX_FMT_VYUY    v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16  YUV 4:2:2     */
#define V4L2_PIX_FMT_Y41P    v4l2_fourcc('Y', '4', '1', 'P') /* 12  YUV 4:1:1     */
#define V4L2_PIX_FMT_YUV444  v4l2_fourcc('Y', '4', '4', '4') /* 16  xxxxyyyy uuuuvvvv */
#define V4L2_PIX_FMT_YUV555  v4l2_fourcc('Y', 'U', 'V', 'O') /* 16  YUV-5-5-5     */
#define V4L2_PIX_FMT_YUV565  v4l2_fourcc('Y', 'U', 'V', 'P') /* 16  YUV-5-6-5     */
#define V4L2_PIX_FMT_YUV32   v4l2_fourcc('Y', 'U', 'V', '4') /* 32  YUV-8-8-8-8   */
#define V4L2_PIX_FMT_HI240   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
#define V4L2_PIX_FMT_M420    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved *//* two planes -- one Y, one Cr + Cb interleaved  */
#define V4L2_PIX_FMT_NV12    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
#define V4L2_PIX_FMT_NV21    v4l2_fourcc('N', 'V', '2', '1') /* 12  Y/CrCb 4:2:0  */
#define V4L2_PIX_FMT_NV16    v4l2_fourcc('N', 'V', '1', '6') /* 16  Y/CbCr 4:2:2  */
#define V4L2_PIX_FMT_NV61    v4l2_fourcc('N', 'V', '6', '1') /* 16  Y/CrCb 4:2:2  */
#define V4L2_PIX_FMT_NV24    v4l2_fourcc('N', 'V', '2', '4') /* 24  Y/CbCr 4:4:4  */
#define V4L2_PIX_FMT_NV42    v4l2_fourcc('N', 'V', '4', '2') /* 24  Y/CrCb 4:4:4  *//* two non contiguous planes - one Y, one Cr + Cb interleaved  */
#define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
#define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
#define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
#define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
#define V4L2_PIX_FMT_NV12MT  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 16x16 macroblocks *//* three planes - Y Cb, Cr */
#define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
#define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 12  YVU411 planar */
#define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
#define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16  YVU422 planar *//* three non contiguous planes - Y, Cb, Cr */
#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12  YVU420 planar */
#define V4L2_PIX_FMT_YUV422M v4l2_fourcc('Y', 'M', '1', '6') /* 16  YUV422 planar */
#define V4L2_PIX_FMT_YVU422M v4l2_fourcc('Y', 'M', '6', '1') /* 16  YVU422 planar */
#define V4L2_PIX_FMT_YUV444M v4l2_fourcc('Y', 'M', '2', '4') /* 24  YUV444 planar */
#define V4L2_PIX_FMT_YVU444M v4l2_fourcc('Y', 'M', '4', '2') /* 24  YVU444 planar */

大概有这么多的YUV格式,它们的数据存储格式都是不太一样的,具体的存放格式可以参考官方文档:http://v4l.videotechnology.com/dwg/v4l2.pdf

此处,我就用我之前所用到个格式来举例:V4L2_PIX_FMT_NV12,以下是官方文档中的示例:

上面的图表代表YUV数据实际存放的方式,U对应Cb,V对应Cr。比如一张100*100像素的图片,那么Y数据就占前100*100个字节,UV数据占后面 (100*100)/2 个字节。

下面图表代表YUV数据是如何从图像中取得的。比如左上角像素(0,0),(0,1),(1,0),(1,1)公用一个C数据,也就是UV数据。但是他们的Y分量都是各自的。通过上面的表,我们可以将内存中V4L2采集到的数据的YUV分量先分辨出来。然后再根据下面的表,还原出原始图片的每一个像素的YUV分量,即:

还原后像素YUV分量,以第一行为例
  0,0 0,1 0,2 0,3
Y Y00 Y01 Y02 Y03
U Cb00 Cb00 Cb01 Cb01
V Cr00 Cr00 Cr01 Cr01

还原了每一个像素的YUV分量后,接下来就一个像素一个像素的转换成RGB即可。转换公式网上很容易找到,不过这里还是贴一下,省去再搜索的时间:

R = Y + 1.4075 * (V-128);  
G = Y - 0.3455 * (U-128) - 0.7169*(V-128);  
B = Y + 1.779 * (U-128);

有了此处的公式,转换RGB就很容易了,以下为C实现的YUV420(V4L2_PIX_FMT_NV12格式的)转RGB代码:

typedef unsigned char uchar;
typedef unsigned int uint;static inline uchar rgb_overflow_guard(int rgb)
{if (rgb > 255){return 255;}if (rgb < 0){return 0;}return rgb;
}// change yuv420(nv12) to rbg, return a pointer to rgb buffer
uchar *nv12_to_rgb(const uchar *yuvBuf, uint width, uint height)
{int row, col;int Y, U, V, R, G, B;const uchar *pY, *pU; // pointer to Y data, U data. V data follow the U datauchar *rgbBuf = NULL;uchar *pixel = NULL; // pointer to a rgb pixel// parameter checkassert(yuvBuf);assert(width);assert(height);rgbBuf = (uchar *)malloc(width * height * 3);if (!rgbBuf){return NULL;}pY = yuvBuf;pU = yuvBuf + width * height;for (row = 0; row < height; row++){for (col = 0; col < width; col++){Y = pY[row * width + col];U = pU[(row / 2) * (width / 2) + col / 2];V = pU[(row / 2) * (width / 2) + col / 2 + 1];R = rgb_overflow_guard(Y + 1.4075 * (V - 128));G = rgb_overflow_guard(Y - 0.3455 * (U - 128) - 0.7169 * (V - 128));B = rgb_overflow_guard(Y + 1.779 * (U - 128));pixel = rgbBuf + (row * width + col) * 3;pixel[0] = R;pixel[1] = G;pixel[2] = B;}}return rgbBuf;
}

总之,要进行YUV转码RGB,首先得搞清楚你所拿到的YUV的格式是什么,这个可以结合官方文档去看。然后才能选择对应格式的转码代码,否则,轻则转码异常,重则SEGMENTFAULT,段错误,core down。

V4L2 YUV/YCbCr格式数据 转 RGB格式数据 V4L2_PIX_FMT_NV12 转 RGB相关推荐

  1. YUV / RGB 格式及快速转换

    YUV是指亮度参量和色度参量分开表示的像素格式,而这样分开的好处就是不但可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大. YUV是一个比较笼统地说法,针对它的具体排列方式,可以分为很 ...

  2. YUV / RGB 格式及快速转换算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...

  3. 【DSP开发】【VS开发】YUV与RGB格式转换

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  4. 使用C++实现YUV格式图像与RGB格式图像之间相互转换

    使用C++实现YUV格式图像与RGB格式图像之间相互转换 一.RGB与YUV转换公式 1.RGB转YUV 1)RGB转换亮度与色差信号公试: 2)归一化为YUV的转化公试为: 2.YUV转RGB 二. ...

  5. YUY2(YUV) 与 RGB 格式图片的相互转换 以及 基于YUY2(YUV)的blending

    这是一个项目里使用的,API里从pool里取出的格式都是YUY2,但是图像处理的API库中要求都是jepg格式. YUY2经常用于电视制式以及许多摄像头的输出格式.而我们在处理时经常需要将其转化为RG ...

  6. YUV 格式与 RGB 格式的相互转换公式总结(C++版)

    YUV 格式与 RGB 格式的相互转换公式 最近在用的一个工业相机,输出的图像格式是 YUY2 格式.而在电脑上显示时需要 RGB 格式,所以就花了些时间在网上查了些相关的资料.说实话,网上关于 YU ...

  7. 通过V4L2框架获取UVC摄像头的MJPEG格式数据

    UVC摄像头一般支持YUV,MJPEG,H264等格式的输出,下面以MJPEG输出为例,介绍如何通过V4L2框架抓取摄像头MJPEG数据. #include <stdio.h> #incl ...

  8. YUY2(YUV) 与 RGB 格式图片的相互转换

    [版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/jtujtujtu/article/d ...

  9. 数据压缩实验一:yuv转rgb格式实验报告

    数据压缩实验一:yuv转rgb格式实验报告 一:实验基本原理 yuv转rgb格式转换公式: R=Y+1.4020*(V-128) G=Y-0.3441*(U-128)-0.7141*(V-128) B ...

  10. YUV与RGB格式详解

    YUV 是一种颜色编码方法,和它等同的还有 RGB 颜色编码方法. RGB 颜色编码 RGB 三个字母分别代表了 红(Red).绿(Green).蓝(Blue),这三种颜色称为 三原色,将它们以不同的 ...

最新文章

  1. VMware 虚拟化编程(4) — VDDK 安装
  2. 刚安装了Fedora 33,尝尝鲜~,哈哈~~~
  3. 【Socket】linux套接字技术之tcp
  4. 仓库处理中 无法修改_阿里云自研数据仓库 AnalyticDB 再捧 TPC 全球冠军
  5. delphi xe http 收不到反馈消息_好消息接二连三!苹果将在双·11当天举办发布会_笔记本新闻...
  6. 利用XML生成Excel
  7. 公需科目必须学吗_专业技术人员一般公需科目学习的通知
  8. java和asp.net core_干货分享:ASP.NET CORE(C#)与Spring Boot MVC(JAVA)异曲同工的编程方式总结...
  9. AGC022E Median Replace
  10. MySQL数据库教程之十四:MySQL触发器
  11. Android聊天软件开发(基于网易云IM即时通讯)——发送文本消息(四)
  12. C语言实现2048游戏(分文件编译)
  13. speedoffice(PPT)怎么将背景设置为渐变背景
  14. 公众平台--扫描微信二维码,关注后自动登录
  15. UML时序图速查——架构设计必备技能
  16. 【青龙面板】天翼云盘签到
  17. 【微信小程序】一文读懂,数据请求
  18. 安卓中为了获取context的方法和区别(getContext,getActivity,this,mainActivity.this等)
  19. cosh()函数以及C ++中的示例
  20. JavaScript实现图片文字识别与读取

热门文章

  1. Excel处理数据技巧
  2. 应用comsol模拟水力压裂应力分布
  3. Python UI自动化 编程(一) UIAutomation
  4. JavaWeb 学习路线
  5. 并发测试工具Jmeter安装与简单使用
  6. ecshop内页显示最新文章
  7. 北京航空航天大学计算机考研资料汇总
  8. java---金额中文大小写实时转换小程序
  9. 3个方法解决百度网盘限速问题
  10. 一款完全仿照E盾的源码(服务端+代理端+客户端)