【opencv】YUV各种色彩、YUV420sp2RGB

对于 YUV 所表示的图像,Y 和 UV 分量是分离的。如果只有 Y 分量而没有 UV 分离,那么图像表示的就是黑白图像。彩色电视机采用的就是 YUV 图像,解决与和黑白电视机的兼容问题,使黑白电视机也能接受彩色电视信号。

人眼对色度的敏感程度低于对亮度的敏感程度。主要原因是视网膜杆细胞多于视网膜锥细胞,其中视网膜杆细胞的作用就是识别亮度,视网膜锥细胞的作用就是识别色度。所以,眼睛对于亮度的分辨要比对颜色的分辨精细一些。

利用这个原理,可以把色度信息减少一点,人眼也无法查觉这一点。

所以,并不是每个像素点都需要包含了 Y、U、V 三个分量,根据不同的采样格式,可以每个 Y 分量都对应自己的 UV 分量,也可以几个 Y 分量共用 UV 分量。相比 RGB,能够节约不少存储空间。

YUV 4:4:4采样方式与 RGB 图像大小是一样的。
YUV 4:2:2相比 RGB, 节省了三分之一的存储空间。
YUV 4:2:0相比 RGB, 节省了一半的存储空间。

设实际宽高为w*h的图像,如果是RGB格式,那么他的数据量为w*h*3
如果是yuv420格式,那么他的数据量为w*h*1.5
因为yuv4:4:4的数据量等于RGB数据量,而yuv4:4:4yuv4:2:0数据量的2倍,所以yuv4:2:0的数据量为w*h*3/2

yuv420sp转化得到RGB的步骤:
  • 1.当我们拿到一帧图像的yuv原始数据后,首先需要明确拿到的是以下哪种yuv数据:yuv4:4:4yuv4:2:2yuv4:2:0。并且,我们都会知道给对应图像的宽和高,因为这都是驱动配置给出的。如果你是从yuv元素数据中截取出来的某roi区域的yuv数据,那么你也应该知道该roi的宽和高。注意,此时的宽和高是指图像的宽和高,不是指代图像数据码流排列的行数和列数。
  • 2.把原始yuv数据通过构造cv::Mat格式封装起来,此时的cv::Mat的宽(.cols)和高(.rows)就需要变化了,因为yuv格式和RGB格式的数据量是不一样的,yuv格式如果不是yuv4:4:4(yuv数据量为w*(h*3))的话,那么yuv格式的数据量是一定比RGB少的。所以,此时如果是yuv420格式,就根据yuv420格式的特点,把cv::Mat的宽高设置为w*(h*1.5),且必须为单通道,注意这里宽度不变,是在高度上延伸。yuyv原始数据变成cv::Mat格式后,你如果直接imshow显示的话,图像会变高。转化成RGB格式后才会恢复为正常宽和高。
  • 3.然后再通过cv::cvtColor(yuyv_img, rgb_img, cv::COLOR_YUV420sp2RGB);转化得到RGB图像。

注意构造yuyv的cv::Mat时通道类型是CV_8UC1,而构造RGB的cv::Mat时通道类型是CV_8UC3.

cv::Mat yuyv_img =
    cv::Mat(box.height * 3 / 2, box.width, CV_8UC1,
            const_cast<unsigned char *>(yuv_raw.data()));
if (!yuyv_img.data) {
  std::cout << "empty yuyv_img"<< std::endl;
}
cv::Mat rgb_img = cv::Mat(box.height, box.width, CV_8UC3);
cv::cvtColor(yuyv_img, rgb_img, cv::COLOR_YUV420sp2RGB);

可参考下面两篇文章来理解YUV:
一文理解 YUV
YUV色彩格式总结

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值