基于无人机的实时图传系统
2019-09-12严羽王永众杨来邦
严羽 王永众 杨来邦
摘 要:民用领域上无人机的航拍系统,不仅给专业工作者带来方便,还给普通生活带来了乐趣。本文以无人机本身自带的图传系统为基础通过视频处理技术将视频流处理后通过Android手机4G网络实时上传到搭建好的服务器上,同时也将无人机飞行参数一并上传,然后通过PC端获取服务器的视频流数据以及飞行参数,PC端通过软件能实时显示前方无人机拍摄的画面以及当前无人机的飞行状态。
关键词:无人机;实时图传;视频传输文章编号:2095-2163(2019)04-0065-06 中图分类号:TP311.52 文献标志码:A
0 引 言
无人机出现在1917年,早期的无人驾驶飞行器的研制和应用主要用作靶机,应用范围主要是在军事上,后来逐渐用于作战、侦察及民用遥感飞行平台。20世纪80年代以来,随着计算机技术、通讯技术的迅速发展以及各种数字化、重量轻、体积小、探测精度高的新型传感器的不断面世,无人机的性能不断提高,应用范围和应用领域迅速拓展。世界范围内的各种用途、各种性能指标的无人机的类型已达数百种之多。续航时间从1 h延长到几十个h,任务载荷从几kg到几百kg,这为长时间、大范围的遥感监测提供了保障,也为搭载多种传感器和执行多种任务创造了有利条件。
近年来,传统的卫星遥感系统,已经不能够满足于高分辨率影像的需求,所以在这样的情形之下,无人机[1]因其自身所独有的优势被广泛应用,成为了卫星遥感系统检测的补充。
无人机遥感技术可快速地对地质环境信息和过时的 GIS数据库进行更新、修正和升级 。为政府和相关部门的行政管理、土地、地质环境治理,提供及时的技术保证。
随着国家改革开放的逐步深入,经济建设迅猛发展,各地区的地貌发生巨大变迁。现有的航空遥感技术手段已无法适应经济发展的需要。新的遥感技术为日益发展的经济建设和文化事业服务。以无人驾驶飞机为空中遥感平台的技术,是为适应这一需要而发展起来的一项新型应用性技术,能够较好地满足现阶段国家对航空遥感业务的需求,对陈旧的地理资料进行更新。
目前低空无人机遥感技术在航拍、航测、国土、农业、环保、应急救灾和科学研究等领域应用广泛[2-3],无人机遥感航空技术以低速无人驾驶飞机为空中遥感平台,用彩色、黑白、红外、摄像技术拍摄空中影像数据;并用计算机对图像信息加工处理。该系统在设计和最优化组合方面具有突出的特点,是集成了遥感、遥控、遥测技术与计算机技术的新型应用技术。
1 无人机飞行参数获取与图传系统
1.1 软硬件平台简介
(1)大疆系列无人机一台;
(2)搭载Android系统手机一台(要带有4 G流量卡);
(3)X86系列多核处理服务器一台,该服务器要固定IP同时要有大容量带宽;
(4)通用计算机一台作为接收终端使用。
本文无人机采用大疆精灵系列无人机。该无人机搭载了6个视觉传感器、主相机、2组红外传感器、1组超声波传感器、GPS/GLONASS双模卫星定位系统、IMU和指南针雙冗余传感器。通过无人机的无线传输设备连接遥控器,遥控器一端与手机相连。无人机将拍摄到的图像画面以及飞行参数通过无线传回到遥控器,手机从遥控器获取数据并通过4G网络传递到已经搭建好的服务器平台,PC端通过网络可以实时获取无人机拍摄的影像以及各飞行参数。
1.2 H264视频流简介
H264是新一代的编码标准,以高压缩、高质量和支持多种网络的流媒体传输著称[4]。在H264协议里定义了3种帧:完整编码的帧叫I帧;参考之前的I帧生成的只包含差异部分编码的帧叫P帧;参考前后的帧编码的帧叫B帧。 H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。3种帧的说明:
1.2.1 I帧
I帧:帧内编码帧。为关键帧,是一帧画面的完整保留;解码时只需要I帧就可以完成。
I帧特点:
(1)解码时仅用I帧的数据就可重构完整图像;
(2)I帧是P帧和B帧的参考帧;
(3)I帧是基础帧即第一帧,在一组中只有一个I帧;
(4)帧所占数据的信息量比较大。
1.2.2 P帧
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。
P帧特点:
(1)P帧是I帧后面相隔1~2帧的编码帧;
(2)P帧采用运动补偿的方法传送其与前面的I或P帧的差值及运动矢量(预测误差);
(3)解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
(4)P帧属于前向预测的帧间编码。其只参考前面最靠近其的I帧或P帧;
(5)由于P帧是参考帧,可能造成解码错误的扩散。
1.2.3 B帧
B帧:双向预测内插编码帧。是双向差别帧,也就是B帧记录的是本帧与前后帧的差别。要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面与本帧数据的叠加取得最终的画面。
B帧特点
(1)B帧是由前面的I或P帧和后面的P帧来进行预测的;
(2)B帧传送的是其与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
(3)B帧压缩比最高,因为其只反映参考帧间运动主体的变化情况,预测比较准确;
H264功能分为2层:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输[5]。因此每帧数据就是一个NAL单元(SPS与PPS除外)。在实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧。
通过NALU类型人们可以判断帧类型见表1。
以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后:
(1)第1位禁止位,值为1表示语法出错;
(2)第2~3位为参考级别;
(3)第4~8为是nal单元类型。
图1所示是从无人机视频流中截取的视频文件,以16进制的格式打开的视频流数据。
从划红线处可以看出以00 00 00 01分割之后有67 68 65 61
其中,0x67的二进制码为:0110 0111
4-8位00111,转为十进制7,参考表1,7对应序列参数集SPS。
其中,0x68的二进制码为:0110 1000
4-8位01000,转为十进制8,参考表1,8对应图像参数集PPS。
其中,0x65的二进制码为:0110 0101
4-8位00101,转为十进制5,参考表1,5对应IDR图像中的片(I帧)。
其中,0x61的二进制码为:01100001
4-8位00001,转为十进制1,参考表1,1对应非IDR图像的片即非I帧,因为该帧在I帧后面则根据P帧特点可以判断出是P帧而不可能是B帧。
H264的SPS和PPS串,包含了初始化H264解码器所需要的信息参数,包括编码所用的profile、level、图像的宽和高,deblock滤波器等。SPS中的信息至关重要。如果其中的数据丢失或出现错误,那么解码过程很可能会失败,分离H264码流时,需要首先写入SPS和PPS,否则会导致分离出来的数据没有SPS、PPS而无法播放。
1.3 H264视频流处理
手机端实时从遥控器获取的H264视频流是一段非常简短且由多个或一个帧组成的流文件。如图1所示,所做的工作就是把每一帧给分离出来。处理的方法是组建一个通道,该通道的作用是一端一直获取传输过来的H264视频流且将该视频流的每一帧分离出来,通过管道传输到另一端。而另一端封装成flv的格式通过网络发送到服务器,为保证视频质量以及实时性,上述过程都是并行化执行。因为实时图传对运行效率有较高的要求,因此上述涉及到大量运算的过程都是在c环境中运行的。
1.4 RTMP协议
本地视频流数据需要通过流媒体协议(如RTMP、HTTP、UDP、TCP、RTP等)推送至服务器,而本文以RTMP协议推送为主。
RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种[6]。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括Adobe Media Server/Ultrant Media Server/red5等。
通过从官网下载的开源函数库编译后的libtrmp提供的API来进行推流,其中的RTMP协议已经封装在相关函数中。librtmp提供的API中只需要常见的几个API就可以将数据流推送到服务器,所需要的API如下:
RTMP_Init()//初始化结构体
RTMP_Free()
RTMP_Alloc()
RTMP_SetupURL()//设置rtmp server地址
RTMP_EnableWrite()//打开可写选项,设定为推流状态
RTMP_Connect()//建立NetConnection
RTMP_Close()//关闭连接
RTMP_ConnectStream()//建立NetStream
RTMP_DeleteStream()//删除NetStream
RTMP_SendPacket()//发送数据
推流函数流程如图2所示。
1.5 基于RTMP协议的H264推流器
通过RTMP协议将H264格式的视频流发送到服务器中实现推流效果具体程序流程如图3所示。
整个程序框图包含4个接口函数:
GetH264():获取H264视频流数据。
RTMPH264_Connect():建立RTMP连接。
RTMPH264_Send():发送数据。
RTMPH264_Close():关闭RTMP连接。
按照先后顺序依次调用上述函数可以推流H264格式视频流到服务器。上述4个接口函数中又包含以下函数,这些函数主要功能如下:
GetH264()中包含以下函数:
FilterH264():对原始视频流过滤。
H264toMem():對接收到的H264视频流以队列的形式放入内存缓存中。
RTMPH264_Connect()中包含以下函数:
InitSockets():初始化Socket。
RTMP_Alloc():为结构体“RTMP”分配内存。
RTMP_Init():初始化结构体“RTMP”中的成员变量。
RTMP_SetupURL():设置输入的RTMP连接的URL。
RTMP_EnableWrite():发布流的时候必须要使用。如果不使用则代表接收流。
RTMP_Connect():建立RTMP连接,创建一个RTMP协议规范中的NetConnection。
RTMP_ConnectStream():創建一个RTMP协议规范中的NetStream。
RTMPH264_Send()中包含以下函数:
ReadFirstNaluFromBuf():从内存中读取出第一个NAL单元。
ReadOneNaluFromBuf():从内存中读取出一个NAL单元。
H264_decode_sps():解码SPS,获取视频的宽、高、帧率信息。
SendH264Packet():发送一个NAL单元。
SendH264Packet()中包含以下函数:
SendVideoSpsPps():如果是关键帧,则在发送该帧之前先发送SPS和PPS。
SendPacket():组装一个RTMPPacket,调用RTMP_SendPacket()发送出去。
RTMP_SendPacket():发送一个RTMP数据RTMPPacket。
RTMPH264_Close()中包含以下函数:
RTMP_Close():关闭RTMP连接。
RTMP_Free():释放结构体“RTMP”。
CleanupSockets():关闭Socket。
1.6 服务器技术
由于视频的实时性对服务器提出较高的要求,数据传输时要尽量避免延迟所以选用较为成熟的nginx web服务器来接收发送过来的视频流。
Nginx("engine x")是一款由俄罗斯程序设计师Igor Sysoev所开发高性能的 Web和反向代理服务器,也是一个 IMAP/POP3/SMTP代理服务器[7]。该服务器具有以下优势:
(1)Nginx使用基于事件驱动架构,使得其可以支持数以百万级别的TCP连接。
(2)高度的模块化和自由软件许可证使得第三方模块层出不穷。
(3)Nginx是一个跨平台服务器,可以运行在Linux、 FreeBSD、 Solaris、 AIX、 Mac OS、 Windows等操作系统上。
最重要的一点是该服务器完全开源,可以通过自己的需要专门定制自己的需求同时该服务器具有的模块化更易于开发和维护,这些优秀的设计带来的极大的稳定性能,使得大量从事软件开发的人员使用和维护之。
Nginx带有的RTMP模块使得配置该服务器变得非常简单且高效,因此配置时只要修改nginx.conf配置文件就行,在配置文件中主要加入以下程序:
rtmp {
server {
listen 1935;
application rtmplive{
live on;
record off;
}
}
RTMP表示的是网络传输RTMP协议而非HTTP协议,其中1935是监听端口,服务器一直监听该端口若有数据进来则从该端口拉取数据,获取的数据可以存放在硬盘或内存中,本文涉及到延迟问题则直接存放在内存中。
1.7 程序流程图及主要代码
具体的程序流程如图4所示。
上述流程是无人机视频流部分,下面是关于无人机相关参数获取过程,其中包括:高度、速度、经纬度、飞行参数等。
Aircraft aircraft = (Aircraft) DJISDKManager.getInstance().getProduct();
if(aircraft!=null){aircraft.getFlight Controller().setStateCallback(new
FlightControllerState.Callback(){
Public void onUpdate(FlightController State flightControllerState){
if (flightControllerState.getGPSSignal Level() != null) {
GPSSignalLevel gpsSignalLevel=flight ControllerState.
getGPSSignalLevel();
....}
}
});}
函数onUpdate()是获取无人机飞行时的相关参数包括GPS信号强度、当前飞行的高度、速度、经纬度、飞行时的姿态角等。
public String SendData(String url, Wurenji express, String contentType) {
try {
vehicle = new JSONStringer().object().key("Wurenji").object()
.key("guid").value(express.guid)
.key("Site").value(express.Site)
.key("Pitch").value(express.Pitch)
.key("Yaw").value(express.Yaw)
.key("Roll").value(express.Roll)
....
.endObject();
StringEntity entity = new StringEntity(vehicle.toString(), encode);