返回 登录
29

Android 特效直播实现原理解析

  作者简介:
  
  2010年开始从事Android开发工作,网易资深开发工程师,主要负责视频云Android端的直播SDK开发与维护工作。
  
  这篇文章主要讲解下目前市面上比较新颖的特效直播,比如Faceu激萌等软件的具体实现原理。
  
图片描述
  
  如上图所示,要实现特效直播至少需要实现这五个模块:相机采集、设备运动方向检测、人脸识别功能、本地预览绘制以及编码发送。下面我们就逐个介绍下在Android端这个五个功能的大致实现原理。
  
  Camera采集
  
  想正常的看到摄像头所采集的图像?只需要给Camera指定一个SurfaceView,具体来讲是给相机设置一个画布(SurfaceHolder)即通过Camera setPreviewDisplay方法,就可以了。这是由于Android的系统API对Camera进行了很好的封装,使得我们可以非常快速的开发一个相机应用。
  
  但在特效直播中,我们需要对相机采集的图像进行处理,比如美颜或是贴上兔耳朵、牙齿等道具图片。然后将处理过的图像显示到屏幕上实时进行观看。这时候让系统帮我们绘制相机图像显然就不合适了。
  
  SurfaceTexture
  
图片描述
  
  这是Android API文档中关于SurfaceTexture的描述,从中我们可以看到SurfaceTexture可以代替SurfaceHolder来接受Camera采集的数据流同时不显示到屏幕上。由此可见要实现特效直播首先需要将Camera采集的SurfaceHolder模式替换为SurfaceTexture模式。
  
  方向检测
  
  在处理相机预览时,Android系统为了保证用户无论怎么旋转手机都能看到“正确”的预览画面(这个“正确”是指显示在UI预览界面的画面与你人眼看到的眼前的画面是一致的),系统底层会根据当前手机屏幕的方向对图像Sensor采集到的数据进行了旋转处理,然后才送给显示系统进行显示。因此在采用SurfaceHolder模式下由于系统底层帮我们进行了方向上的处理,因此我们看到的画面都是正的。但在采用SurfaceTexture模式后,由于系统直接向数据流送给了SurfaceTexture,因此在我们自己绘制以及人脸识别时就需要知道设备的预览方向,来保证绘制的角度正确以及人脸识别的成功率。
  
  在Android上我们可以通过OrientationEventListener来实现实时屏幕方向的监听。
  
图片描述
  
  具体的实现代码也很简单,只需要实现OrientationEventListener中的onOrientationChanged方法就可以实时获取到屏幕方向了。
  
图片描述
  
  
  
  人脸识别
  
  Android系统本身就具有人脸识别功能,其中包括静态人脸检测和动态人脸检测。所谓的静态检测即通过android.media.FaceDetector 这个类对单张图片进行识别,然后识别出图片中的人脸位置。
  
图片描述
  
  在Android 4.0以前需要实现相机实时的人脸识别,只能通过获取Camera采集回调onPreviewFrame将Camera采集的帧数据转化为bitmap送给FaceDetector进行检测。网上有人也实现过这种方式。
  
  
  
图片描述
图片描述
  
  但这种方式实现效率太低,在直播这种场景下基本没人这么做。
  
  在Android 4.0之后,Camera新增了FaceDetectionListener接口
  
图片描述
  
  我们可以通过在开启Camera时设置FaceDetectionListener,来让系统帮我们进行实时的相机人脸检测。FaceDetectionListener可以检测出人脸的大小框以及眼睛和嘴巴的位置。这里有一个需要注意的是检测到人脸rect默认是以预览界面为坐标系,这个坐标系是经过变换的,中心点为(0, 0),左上顶点坐标是(-1000, -1000),右下顶点是(1000, 1000).也就是说不管预览预览Surfaceview多大,检测出来的rect的坐标始终对应的是在这个变换坐标系。而Android里默认的view的坐标系是,左上顶点为(0, 0),横为x轴,竖为y轴。这就需要把rect坐标变换下。
  
图片描述
  
  基本上简单的需求FaceDetectionListener就可以满足了。但复杂的需求,如检测鼻子,眉毛以及平台通过性和对性能要求极高的场景下FaceDetectionListener也有点力不从心了。
  
  目前市面上很多的人脸识别都是基于开源项目OpenCV实现的,OpenCV也有Android平台的实现。对于如何在Android上集成OpenCV的方式,有兴趣的同学可以参考下
  
  OpenGL绘制与编码
  
  SurfaceTexture是GPU纹理,天生与openGL亲近。因此Camera采用SurfaceTexture方式基本上都是通过GLSurfaceView的Render生成SurfaceTexture纹理然后绑定Camera进行绘制,同时可以将SurfaceTexture上Camera采集的数据直接进行硬件编码,提供编码效率。
  
  SurfaceTexture方式由于需要OpenGL基础以及硬件编码相关知识,因此本文中就暂不介绍了,等先普及过OpenGL相关知识后再进行讲解。
  

评论