基于安卓的视频遥控小车的安卓程序能够使用手机后置摄像头实时地将手机拍到的图像传送到电脑端,同时接收电脑端发出的指令。根据电脑的指令手机再发送相应的红外遥控信号给小车,手机安卓程序主要是实现自定义相机、实时视频传输和红外信号传输等功能。
开发环境用的是ADT Bundle,集成了Eclipse、ADT插件和SDK Tools,安装好JDK即可开始开发,方便使用者进行相关的应用开发。
一、摄像头
手机端的摄像头采集到的原始数据数据是YUV格式。建立YuvImage对象image用来存储YUV格式的原始数据。原始数据太大,需要再通过调用image.compressToJpeg()将YUV格式图像数据转为jpg格式。然后启动发送线程,通过socket将每一帧的图像发送到电脑端接收,电脑窗体再一帧一帧播放,形成视频效果。
由于时间不足,所以没有再花时间去学习相关的视频流处理原理和技术。在此使用的是动画播放原理。在基于安卓的视频遥控小车——电脑端开发也说到了,实时视频是通过电脑窗体一帧一帧播放图片,形成视频动画效果。摄像头采集到的是最低分辨率,这样每一帧图像的数据量就小了,延迟也就下去了。
手机端实时视频功能的程序流程图如下图所示。
下面来对主要步骤进行详细介绍。
对于摄像头的操作实际上是安卓自定义相机开发。直接控制相机,比调用系统相机要难一些。首先要访问相机资源,打开摄像头的语句如下。
Camera.open(id);
Id表示摄像头的编号,后置摄像头为0,前置摄像头为1。在调用open()时不传入参数指定打开哪个摄像头,默认是0。
摄像头采集到的原始数据是YUV格式的数据,结构如下,其参数作用如下表所示。
YuvImage image = new YuvImage(byte[] yuv,
int format,
int width,
int height,
int[] strides);
参数 | 类型 | 作用 |
yuv | byte | YUV数据。在多个图像平面的情况下,所有平面必须连接成单个字节数组。 |
format | int | YUV数据格式,如ImageFormat。 |
width | int | YuvImage的宽度。 |
height | int | YuvImage的高度。 |
strides | int | (可选)每个图像平面的行字节。如果yuv包含填充,则必须提供每个图像的步幅。如果strides为null,则该方法假定没有填充,并按格式和宽度本身派生行字节。 |
调用image.compressToJpeg()将YUV格式图像数据转为jpg格式代码如下,其参数作用如下表所示。
image.compressToJpeg(Rect rectangle,
int quality,
OutputStream stream);
参数 | 类型 | 作用 |
rectangle | Rect | 要压缩的矩形区域。方法检查矩形是否在图像内。此外,如果矩形中的色度像素与其中的亮度像素不匹配,则该方法修改矩形。 |
quality | int | 提示压缩机,范围0-100。0表示压缩小尺寸,100表示压缩以获得最高质量。 |
stream | OutputStream | OutputStream写入压缩数据。 |
预览一般用SurfaceView显示摄像头采集到的画面内容。需要用到preview class。这个类需要实现android.view.SurfaceHolder.Callback接口,并用此接口把摄像头采集到的画面送到当前的预览界面。
当应用调用完摄像头之后,必须进行清理释放资源的操作。必须释放Camera对象,不然的话可能会引起其他应用程序使用Camera实例的时候发生崩溃。相应代码如下。
if (mCamera != null) {
mCamera.stopPreview();//停止预览
//调用release()以释放相机以供其他应用程序使用。应用程序应在onPause()期间 //立即释放相机,并在onResume()期间重新open()。
mCamera.release();
mCamera = null;
}
二、红外遥控
此部分代码
http://www.pudn.com/Download/item/id/3913496.html
对应的电脑端程序详见基于安卓的视频遥控小车——电脑端开发
参考文献
感谢以下博主的文章
Google Android官方培训课程中文版——控制相机硬件
关于降低android手机摄像头预览分辨率 - 莹波&微步
Android Studio+Eclipse 利用socket实现视频的实时传输与接收