摄像头:输出图像YUV格式理论知识

本篇文章主要记录一下camera2输出摄像头的编码格式,及数据之间转换。本文章参考链接:
https://blog.csdn.net/qq_39312146/article/details/129252235。
http://www.360doc.com/content/21/0522/14/17136639_978452591.shtml
只为了记录使用。

一、Camera2 获取摄像头数据代码

mImageReader = ImageReader.newInstance(mCameraWidth,mCameraHeight, ImageFormat.YUV_420_888,2);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mChildHandler);private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {//这里一定要调用reader.acquireNextImage()和img.close方法否则不会一直回掉了Image img = reader.acquireLatestImage();if (img == null) {
//                Log.d("lilitest","img is null");return;} else {
//                Log.d("lilitest","img is not null");}byte[] bytes = Utils.getDataFromImage(img);}};

上述代码是camera2通过ImageReader获取摄像头图像的主要代码。获取到Image之后,将image转化为byte数据,通过opencv,ffmpeg等工具对摄像头画面进行处理,之后显示。本文主要记录各种编码的区别,及编码格式。

使用ImageReader.newInstance(mCameraWidth, mCameraHeight, ImageFormat.YUV_420_888, 2)创建的ImageReader对象将返回一个支持YUV_420_888格式的图像。但是这个格式仅仅是指定了数据的存储格式,并没有具体指定是NV21还是NV12。
实际上,Android Camera2 API并不直接支持返回NV21或NV12格式的图像,而是以YUV_420_888格式返回原始的YUV数据,并通过Plane对象提供对Y、U和V分量的访问。因此,如果你需要将YUV_420_888格式的图像转换为NV21或NV12格式,你需要手动进行转换。

在Camera2中,ImageReader读取摄像头数据,选择的格式只有ImageFormat.YUV_420_888 和ImageFormat.JPEG两种。

1、图像重要特性
在这里插入图片描述
1)image.getPlanes:获取图像的像素平面阵列。返回Plane[],当图像格式设置为ImageFormat.YUV_420_888 时,返回数组长度为3,说明该格式图像由三个单色平面组成。当图像格式设置为ImageFormat.JPEG时,返回数组长度为1,说明该格式图像只有一个单色平面。
2)image.getFormat: 获取此图片的格式。ImageReader设置的是什么格式,这里获取到的就是什么格式。
3)image.getBitsPerPixel:检索ImageFormat的每个像素的位数。

2、单色平面性质
1)plane.getPixelStride : 获取行内连续两个颜色值之间的距离(步长)。我的理解,获取每个平面中两个相邻像素之间的距离。
2)plane.getRowStride:获取行间像素之间的距离。我的理解,获取每行的距离。例如1280X720的图片宽为1280,获取的plane.getRowStride可能也为1280,但是plane.getRowStride有可能与图片的宽度不相同。
3)plane.getBuffer():获取第i个平面的数据,保存到buffer。返回ByteBuffer。

二、camera2 YUV420_888
参考链接:https://blog.csdn.net/qq_39312146/article/details/129252235
是YCbCr的泛化格式,能够表示任何4:2:0的平面和半平面格式,每个分量用8 bits 表示。带有这种格式的图像使用3个独立的Buffer表示,每一个Buffer表示一个颜色平面(Plane),除了Buffer外,它还提供rowStride、pixelStride来描述对应的Plane。

U/V的平(Planar)面和半平面(Semi-Planar)
1、U/V的Planar存储(YUV420P)
YUV420P的平面模式又分为YU12 及 YV12 两种格式。该模式的存储方式为:先保存所有Y分量,然后保存所有U分量,最后保存所有V分量。以4X2 图像为例,三分量保存如下:
在这里插入图片描述
该格式具有y u v三个单色平面。对于1280 * 720 图像来说,像素大小为 1280 * 720 = 921600。每个平面获取的特性如下:
1)y 分量平面: PixelStride = 1; RowStride = 1280; 说明该分量每行有1280个像素,每行中两个像素之间的距离为1。并且该平面有720行。
2)u 分量平面:由于YUV420_888采样模式为4:2:0。三个分量的像素分布格式如下。图片中黑色实心点为y分量,白色空心圆为uv分量。从图中可以看出,上下左右四个y像素共用一组uv像素。u 分量平面获取的PixelStride = 1;RowStride = 640.(每行的像素个数是原图像分辨率的一半,通过图中可以看出每行两个y公用一个u,所以u分量上的像素个数是原分辨率的一半)。通过下图可以看出,u平面的像素个数是原像素个数的1/4,可以计算出u平面分量的行数为:1280 * 720 / 4 / 640 = 360。可以看出u平面分量的列数也为原图片分辨率的一半。
3)v分量平面与u相同。
在这里插入图片描述
注意:平面式的yuv格式分为yu12和yv12两种,其中yu12的数据封装为先平铺所有的y,再平铺所有的u,最后平铺所有的v。
yv12数据封装为先平铺所有的y,再平铺所有的v,最后平铺所有的u。

2、U/V的Semi-Planar存储 (YUV420SP)
YUV420SP的平面模式又分为NV12 及 NV21两种格式。该模式的存储方式为:先保存所有Y分量,然后交叉保存u分量及v分量。以4X2 图像为例,三分量保存如下:
在这里插入图片描述
注意:上图为NV12格式,NV21格式为先v后u,既vuvuvu存储。

该格式具有y u v三个单色平面。对于1280 * 720 图像来说,像素大小为 1280 * 720 = 921600。每个平面获取的特性如下:
1)y 分量平面与420p相同: PixelStride = 1; RowStride = 1280; 说明该分量每行有1280个像素,每行中两个像素之间的距离为1。并且该平面有720行。
2)u 分量平面:由于YUV420_888采样模式为4:2:0。三个分量的像素分布格式如下。图片中黑色实心点为y分量,白色空心圆为uv分量。从图中可以看出,上下左右四个y像素共用一组uv像素。u 分量平面获取的PixelStride = 2;RowStride = 1280.(每行的像素个数是原图像分辨率的一半,通过图中可以看出每行两个y公用一个u,所以u分量上的像素个数是原分辨率的一半)。通过下图可以看出,u平面的像素个数是原像素个数的1/4,可以计算出u平面分量的行数为:1280 * 720 / 4 / 640 = 360。可以看出u平面分量的列数也为原图片分辨率的一半。
3)v分量平面与u相同。
因为uv是交叉分布的,所以索引0 2 4 6 对于u分量有效,索引1 3 5 7 对于v分量有效。
在这里插入图片描述
下面计算对于YUV420_888格式每个像素所占用的bit。通过代码获取ImageFormat.getBitsPerPixel(format) = 12。计算方法如下:
假设图像分辨率为w * h,则y分量的像素个数为wh。u分量像素个数为wh/4。v分量像素个数为wh/4。三分量总的像素个数为wh + wh/2 = 3wh/2。对于wh分辨率的图像的像素点有w*h个,每个占8bit,平均每个像素点占的bit = 1.5 * w * h * 8 / w * h = 12。表达的不够清晰。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/109357.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

管理方法论:5. 团队发展的阶段模型——调整管理策略

概念 布鲁斯塔克曼(Bruce Tuckman)提出团队发展阶段模型。 团队发展的五个阶段是:组建期(Forming)、激荡期(Storming)、规范期(Norming)、执行期(Performing)和休整期&…

使用凌鲨进行聚合搜索

作为研发人员,我们经常需要在多个来源之间查找信息,以便进行研发工作。除了常用的搜索引擎如百度和必应之外,我们还需要查阅各种代码文档和依赖包等资源。这些资源通常分散在各个网站和文档库中,需要花费一定的时间和精力才能找到…

C++之生成详细汇编代码(二百一十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

前端JavaScript修饰器:简化代码,增强功能

​ 🎬 岸边的风:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! ​ 目录 引言 1. 修饰器简介 2. 修饰器语法 3. 类修饰器 应用场景 示例代码 4. 方法修饰器 应用场景 示例代码 5. 属性…

webpack实战:最新QQ音乐sign参数加密分析

文章目录 1. 写在前面2. 接口抓包分析3. 扣webpack代码4. 补浏览器环境5. 验证加密结果 1. 写在前面 现在!很多的网站使用Webpack加载和处理JS文件。所以对于使用了Webpack加载的JS代码,一旦它们被打包并在浏览器中执行,通常是难以直接阅读和…

CSS预编译:提升样式开发效率与可维护性的关键工具

💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 引言 CSS预编译是一项前…

AMEYA360详解芯力特SIT1145AQ收发器芯片CAN FD Passive功能详解

01CAN FD Passive功能说明 芯力特在SIT1145AQ/FD版本中加入了CAN FD Passive功能,CAN FD Passive功能简单来说就是SIT1145AQ/FD在休眠或待机模式下屏蔽总线上的CAN FD报文。 为什么需要CAN FD Passive功能呢? SIT1145AQ的特定帧唤醒只支持CAN报文,当SIT…

跨域问题解决方案(三种)

Same Origin Policy同源策略(SOP) 具有相同的Origin,也即是拥有相同的协议、主机地址以及端口。一旦这三项数据中有一项不同,那么该资源就将被认为是从不同的Origin得来的,进而不被允许访问。 Cross-origin resource…

合宙Air724UG LuatOS-Air LVGL API控件-开关 (Switch)

开关 (Switch) 示例代码 function event_handler(obj, event)if event lvgl.EVENT_VALUE_CHANGED thenprint("State", lvgl.switch_get_state(obj))end endsw1 lvgl.switch_create(lvgl.scr_act(), nil) lvgl.obj_align(sw1, nil, lvgl.ALIGN_CENTER, 0, -50) lvg…

【数据结构初阶】三、 线性表里的链表(无头+单向+非循环链表)

相关代码gitee自取: C语言学习日记: 加油努力 (gitee.com) 接上期: 【数据结构初阶】二、 线性表里的顺序表_高高的胖子的博客-CSDN博客 引言 通过上期对顺序表的介绍和使用 我们可以知道顺序表有以下优点和缺点: 顺序表优点 尾插 和 尾…

LeetCode(力扣)406. 根据身高重建队列Python

LeetCode406. 根据身高重建队列 题目链接代码 题目链接 https://leetcode.cn/problems/queue-reconstruction-by-height/ 代码 class Solution:def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:people.sort(key lambda x: (-x[0], x[1]))que […

恒运资本:沪指震荡涨0.28%,医药板块强势拉升,金融等板块上扬

15日早盘,沪指盘中震荡上扬,科创50指数表现强势;北向资金小幅净流入。 到午间收盘,沪指涨0.28%报3135.31点,深成指、创业板指涨均0.11%,科创50指数涨1.04%;两市合计成交4357亿元,北…