默认
发表评论 0
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
Android 特效直播实现原理解析
阅读(40066) | 评论(0 收藏 淘帖

作者简介


  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相关知识后再进行讲解。


即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:java socket接收的数据是否可通过FileDescriptor映射内存?下一篇:【人物专访】朱玲——我在网易云当女程序媛
推荐方案
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部