本文作者是Lukas Biewald—CrowdFlower的创始人,Lukas曾被《Inc.》杂志评选为30岁以下杰出企业家。CrowdFlower成立于2009年,是一个按需劳动力的大数据平台,帮助企业收集培训数据并进行人机交互机器学习。
Lukas Biewald毕业于斯坦福大学,获得数学学士学位和计算机科学硕士学位。Lukas曾任职Yahoo日本搜索团队主管,之后作为高级数据科学家就职于Powerset,该公司于2008年被微软收购。
深度学习和廉价硬件的探索
早期航空器,1818(来源:维基百科&美国国会数据库)
在制造了一个图像识别机器人后,显然下一步是制作一个可飞行的版本。于是我决定打造一款能够进行面部识别并响应语音命令的自动化无人机。
▍选择一款预制无人机
对无人机进行编程,最难的部分是如何开始,我是从组装无人机零件开始的。但是几乎和之前所有DIY项目一样,自己组装无人机花了我很多的钱。而且坦白的说,我手工打造的无人机一直没有稳定飞行过。可以肯定的是,直接购买预制版本才是更加简单经济的选择。
大多数无人机制造商都声称提供API接口,但对于业余爱好者来说并没有什么明显的优势。市面上带似乎可用的API接口的无人机,大多售价都超过1000美元,这是一个很高的进入门槛。
经过一些调查以后,我发现了Parrot AR Drone 2.0(见下图)。我认为对于业余爱好者来说,这是一款理想的机器。它的价格不高,还可以进行编程。你可以选择花200美元买一台新机器,但由于很多人买了无人机又从来不使用它们,因此购买一台二手机器也是个不错的选择。在eBay上二手无人机的售价大约是130美元甚至更低。
△我收藏的各类无人机,Parrot AR Drone无人机挂在最左边
Parrot AR无人机飞行的稳定性没有更贵的新款 Parrot Bebop 2.0 好(售价大约550美元),但是Parrot AR提供一个好用的node.js客户端库叫做node-ar-drone,很适合在上面进行开发。
另外一个优势:Parrot AR无人机很结实。在测试自动化程序的过程中,无论它被撞墙上、家具上、室内植物上和客人身上,他仍然能够良好的飞行。
相比给地面机器人编程,给无人机编程最糟的地方是电池续航时间短。一块电池需要充电几个小时,才能飞行大约10分钟的时间。因此我建议多买两块备用电池,测试的时候可以循环使用。
▍给我的无人机编程
由于Javascript天生的驱动能力,因此是非常理想的无人机编程语言。相信我,无人机飞行中会遇到很多异步事件。我虽然没有在Node上花费很多时间,但这个语言让我印象深刻。我最近一次认真的为机器人编程使用的是C语言。用C语言处理线程和各种异常是十分痛苦的,因此最好少用。我希望有人为其它无人机平台建立Javascript开发包,因为这个语言让我们处理不确定性的开发事件,变得简单有趣。
架构
我决定在笔记本电脑上运行逻辑,在云端进行机器学习。比起直接在树莓派硬件上运行神经网络,这种架构的延迟更低。我认为这种架构对目前的业余无人机开发项目来说是可行的。
微软、谷歌、IBM和亚马逊都有快速、廉价的云端机器学习API。最终,我选择了微软认知服务API(Cognitive Service API)。因为这是唯一一个提供定制面部识别功能的API。
△无人机的架构
入门
默认情况下,Parrot AR Drone2.0带有可供客户端连接的无线网络。这个功能对编程者来说非常麻烦。每次你希望尝试什么的时候,需要先断开你的网络然后连上无人机的网络。幸运的是,有一个名叫ardrone-wpa2的项目非常有用。它可以通过脚本让无人机加入你自己的WiFi网络。
远程登录到无人机是件十分有趣的事。Parrot运行在一个剥离版本的Linux上。你最近一次使用远程登录功能是什么时候?连接了什么东西?以下是打开终端并直接登录无人机的示例。
% script/connect "The Optics Lab" -p "particleorwave" -a 192.168.0.1 -d 192.168.7.43
% telnet 192.168.7.43
用命令行模式飞行
安装node库以后,创建一个node.js REPL(Read-Evaluate-Print-Loop)并用它引导无人机:
var arDrone = require('ar-drone');
var client = arDrone.createClient({ip: '192.168.7.43'});
client.createRepl();
drone> takeoff()
true
drone> client.animate(‘yawDance, 1.0)
如果你一直跟着做到这步,那么现在你的无人机肯定已经摔过至少几次了。我上千次重新粘贴了安全壳,直到它彻底损坏,不得不买一个新的。我犹豫要不要提这个,实际上Parrot AR在不安装安全壳的情况下飞得更好。但无人机在没有安全壳的情况下更加危险,因为当无人机撞上什么东西时,螺旋桨可能会折断,而且会在家具上留下痕迹。
通过网页控制飞行
为无人机构建基于web的操作界面并不困难,而且结果令人满意(见下图)。使用Express.js框架可以轻松的构建一个漂亮的web服务器。
var express = require('express');
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/land', function(req, res) {
client.land();
});
app.get('/takeoff', function(req, res) {
client.takeoff();
});
app.listen(3000, function () {
});
我设置了一个按钮来实现AJAX请求。
<html>
<script language='javascript'>
function call(name) {
var xhr = new XMLHttpRequest();
xhr.open('GET', name, true);
xhr.send();
}
</script>
<body>
<a onclick="call('takeoff');">Takeoff</a>
<a onclick="call('land');">Land</a>
</body>
</html>
从无人机上获得视频流
我发现使用无人机摄像头发送反馈的最佳方法是打开一个连接,并将我的网络服务器中的PNG连续发送到我的网站。我的网络服务器使用AR无人机库从无人机摄像头中连续拉取PNG图片。
var pngStream = client.getPngStream();
pngStream
.on('error', console.log)
.on('data', function(pngBuffer) {
sendPng(pngBuffer);
}
function sendPng(buffer) {
res.write('--daboundary\nContent-Type: image/png\nContent-length: ' + buff
er.length + '\n\n');
res.write(buffer);
});
在无人机图像上运行人脸识别
Azure的面部API功能强大且易用。它可以识别你上传的朋友照片,也可以猜测年龄和性别,我发现这两个功能的准确率高得令人惊讶。延迟时间约为200毫秒,费用是1.5美元/1,000次。对我开发的这个程序来说,这是完全合理的。下面是关于如何发送一个图像并进行面部识别的代码。
var oxford = require('project-oxford'),
oxc = new oxford.Client(CLIENT_KEY);
loadFaces = function() {
chris_url = "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAALyAAAAJGMyNmIzNWM0LTA5MTYtNDU4Mi05YjExLTgyMzVlMTZjYjEwYw.jpg";
lukas_url = "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/3/000/058/147/34969d0.jpg";
oxc.face.faceList.create('myFaces');
oxc.face.faceList.addFace('myFaces', {url => chris_url, name=> 'Chris'});
oxc.face.faceList.addFace('myFaces', {url => lukas_url, name=> 'Lukas'});
}
oxc.face.detect({
path: 'camera.png',
analyzesAge: true,
analyzesGender: true
}).then(function (response) {
if (response.length > 0) {
drawFaces(response, filename)
}
});
我使用ImageMagick库来注释PNG图片中的面孔。在这点上有很多可以扩展的方向,如使用情感API确定面部的情绪等。
运行语音识别控制无人机
语音识别部分最棘手的不是语音识别本身,而是以微软的Speech API要求的格式将音频流从网页传输到本地服务器,最终代码的大部分是为了实现这个功能。一旦你能够通过单通道采集到正确频率的音频,这个API就可以很好的工作,而且非常容易使用。它的价格是4美元/1000次请求,这对于业务爱好者的应用来说,基本上算是免费的。
RecordRTC有一个很好的库,这是客户端网络音频录制的好起点。在客户端上,我们可以添加代码来保存音频文件:
app.post('/audio', function(req, res) {
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
form.uploadDir = path.join(__dirname, '/uploads');
form.on('file', function(field, file) {
filename = "audio.wav"
fs.rename(file.path, path.join(form.uploadDir, filename));
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req)
speech.parseWav('uploads/audio.wav', function(text) {
console.log(text);
controlDrone(text);
});
});
我使用FFmpeg程序减少音频采样点,并将其合并为一个通道,上传到微软:
exports.parseWav = function(wavPath, callback) {
var cmd = 'ffmpeg -i ' + wavPath + ' -ar 8000 -ac 1 -y tmp.wav';
exec(cmd, function(error, stdout, stderr) {
console.log(stderr); // command output is in stdout
});
postToOxford(callback);
});
自主搜索路径
我用ardrone-autonomy库为我的无人机绘制自动寻径地图。在无人机无数次坠落在客厅的家具和植物上后,我妻子好心的建议我把我的项目搬到车库里去。那里没有太多可破坏的东西了,但也没有太多的空间(见下图)。
△在我的“实验室”里试飞无人机
如果我能获得更大的实验空间,我会继续研究智能搜索算法。但现在我只需要让我的无人机能够起飞、旋转,去寻找我的朋友和敌人:
var autonomy = require('ardrone-autonomy');
var mission = autonomy.createMission({ip: '10.0.1.3', frameRate: 1, imageSize: '640:320'});
console.log("Here we go!")
mission.takeoff()
.zero() // Sets the current state as the reference
.altitude(1)
.taskSync(console.log("Checkpoint 1"))
.go({x: 0, y: 0, z: 1, yaw: 90})
.taskSync(console.log("Checkpoint 2"))
.hover(1000)
.go({x: 0, y: 0, z: 1, yaw: 180})
.taskSync(console.log("Checkpoint 3"))
.hover(1000)
.go({x: 0, y: 0, z: 1, yaw: 270})
.taskSync(console.log("Checkpoint 4"));
.hover(1000)
.go({x: 0, y: 0, z: 1, yaw: 0
.land()
把所有的东西放在一起
看看这个视频,我带着我的无人机起飞去寻找我的朋友克里斯:
小结
一旦建立好一切,你可以通过API控制无人机视频源,无人机编程就变得非常有趣。伴随着新的图像识别技术,给我们提供了各种应用的可能,无论从观察地面植物到在墙壁上作画。Parrot无人机不是为在室内小空间飞行设计的,一个价格更高的无人机能让整个应用变成现实。最终,无人机会变得更加稳定,现实世界中将出现大量类似的应用。
微软的认知服务云API易于使用而且价格便宜。首先,我担心无人机的异常广角摄像头会影响面部识别,而无人机螺旋桨的噪音会干扰语音识别。但总体来说,表现要好于预期。延迟问题也不像我所担心的那样。使用云计算处理实时图像流看起来似乎是个奇怪的架构,但它可能是许多应用的未来之路。
编译:媛媛
★推荐阅读★
招聘 志愿者
希望你有稳定输出的时间,英文能力佳,从业者优先。
加入「AI从业者社群」请备注个人信息
添加小鸡微信 liulailiuwang