音视频篇 - Android 图像处理技术简介

关于 Android 的音视频,也可以叫做多媒体,分成图像、声音和视频。我们先从最基本的图像入手,图像分成 2D 和 3D,Android 自身也提供了很多 API 来实现图像的功能。对于 Android 的图像内存优化,可以看我之前的这篇文章:Android应用篇 - 最全图片相关的优化。

YUV 简介

1. YUV 简介

YUV 是一种颜色编码方法,常使用在各个视频处理组件中。 YUV 在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽。

YUV 是编译 true-color 颜色空间 (colorspace) 的种类,Y'UV, YUV, YCbCr, YPbPr 等专有名词都可以称为 YUV,彼此有重叠。"Y" 表示明亮度 (Luminance、Luma),"U" 和 "V" 则是色度、浓度 (Chrominance、Chroma)。

彩色图像记录的格式,常见的有 RGB、YUV、CMYK 等。彩色电视最早的构想是使用 RGB 三原色来同时传输,这种设计方式是原来黑白带宽的 3 倍,在当时并不是很好的设计。RGB 诉求于人眼对色彩的感应,YUV 则着重于视觉对于亮度的敏感程度,Y 代表的是亮度,UV 代表的是彩度 (因此黑白电影可省略 UV,相近于 RGB),分别用 Cr 和 Cb 来表示,因此 YUV 的记录通常以Y:UV 的格式呈现。

2. 常用的 YUV 格式

为节省带宽起见,大多数 YUV 格式平均使用的每像素位数都少于 24 位。主要的抽样 (subsample) 格式有 YCbCr4:2:0、YCbCr4:2:2、YCbCr4:1:1 和 YCbCr4:4:4。YUV 的表示法称为 A:B:C 表示法:

  • 4:4:4 表示完全取样。
  • 4:2:2 表示 2:1 的水平取样,垂直完全采样。
  • 4:2:0 表示 2:1 的水平取样,垂直 2:1 采样。
  • 4:1:1 表示 4:1 的水平取样,垂直完全采样。

最常用 Y:UV 记录的比重通常 1:1 或 2:1,DVD-Video 是以 YUV4:2:0 的方式记录,也就是我们俗称的 I420,YUV4:2:0 并不是说只有 U (即 Cb) , V(即 Cr) 一定为 0,而是指 U:V 互相援引,时见时隐,也就是说对于每一个行,只有一个 U 或者 V 分量,如果一行是 4:2:0 的话,下一行就是 4:0:2,再下一行是 4:2:0...以此类推。

至于其他常见的 YUV 格式有 YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420 等。

3. YUV 操作

比如在做直播或者美颜相机的时候,因为需要添加美白,滤镜,AR 贴图等效果。所以不能简单的使用 SufaceView 加 Camera 的方式进行数据的采集,而是需要对 Camera 采集到的 YUV 数据进行相关的处理之后然后再进行推流的操作,YUV 数据的返回接口。

 

  @Override
  public void onPreviewFrame(byte[] data, Camera camera) {
   
  }

Android 摄像头采集的数据都是有一定的旋转的。一般前置摄像头有 270 度的旋转,后置摄像头有 90 的旋转。所以要对 YUV 数据进行一定旋转操作,同时对于前置摄像头的数据还要进行镜像翻转的操作。网上一般比较多的算法是关于旋转的:

 

  private byte[] rotateYUVDegree90(byte[] data, int imageWidth, int imageHeight) {
      byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
      // Rotate the Y luma
      int i = 0;
      for (int x = 0; x < imageWidth; x++) {
          for (int y = imageHeight - 1; y >= 0; y--) {
              yuv[i] = data[y * imageWidth + x];
              i++;
          }
      }
      // Rotate the U and V color components
      i = imageWidth * imageHeight * 3 / 2 - 1;
      for (int x = imageWidth - 1; x > 0; x = x - 2) {
          for (int y = 0; y < imageHeight / 2; y++) {
              yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
              i--;
              yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)];
              i--;
          }
      }
      return yuv;
  }
   private byte[] rotateYUVDegree270(byte[] data, int imageWidth, int imageHeight) {
      byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
      // Rotate the Y luma
      int i = 0;
      for (int x = imageWidth - 1; x >= 0; x--) {
          for (int y = 0; y < imageHeight; y++) {
              yuv[i] = data[y * imageWidth + x];
              i++;
          }
      }// Rotate the U and V color compon
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值