用机器视觉追踪四轴飞行器

//编辑:请往下翻,已经准备了视频素材。

//编辑:本文原标题为《四轴飞行器Training Examples》。

//编辑:tensorflow在windows上安装方法请往下翻。

//编辑:请往下翻,更新了数据集。

//编辑:请往更下翻,已经应用了新方案。

要训练就要有样例,没有样例就要自己造。


用Image Magick加一点点js脚本生成,一共1000张。

csv文件里面记录了每张图的文件名,以及飞行器在图中的xy坐标(x向右,y向下,原点在图像中央),以及飞行器在图中的相对尺寸。

打算做End-to-end,用来解决毕业论文(以及一个学校项目)。

[修改于 3 年前 - 2016-12-12 16:06:41]

来自 机器学习
 
2016-11-25 17:29:19
novakon(作者)
1楼
大家都不回帖,而在QQ上跟我吐槽数据集太小。于是做了一份3000张图的,其中有30%的图是没有四轴的,csv中也专门以isempty标出了。



如果还是嫌数据集太小,下面是透明背景的四轴飞行器素材图,可以放到显卡上动态生成训练样例。

折叠评论
1
加载评论中,请稍候...
折叠评论
2016-11-26 17:21:12
2楼
训练2D的图像识别?
折叠评论
加载评论中,请稍候...
折叠评论
2016-11-27 18:48:10
2016-11-27 18:48:10
novakon(作者)
3楼

很快我发现128x128的patch在cpu上慢得无法接受。对各项参数进行调整之后,我生成了新的训练集。


新训练集是64x64黑白图像,其中50%的图像有无人机,50%的图像没有。在训练“图像中有没有无人机”分类器的过程中,我发现如果这个比例不是50%,比如说有无人机的图像占70%,会导致模型朝“所有图片中都有无人机”的方向收敛,因为预测“全都有无人机”的error(0.3)低于随机预测的error(0.5)。

图像背景大多为天空,少部分为景物。

训练采用tensorflow后端 + keras前端,小规模的CNN,图像上下左右翻转作为数据增强,目前训练集(2500)和测试集(500)的accuracy都超过了0.83。肉眼识别率还没做,但是可以感受一下。


图中灰色的表示判断正确,红色的表示判断错误。从训练结果来看,天空背景下准确率较高,花草树木背景下准确率较低。

下面是所用的网络结构(keras):

model = Sequential()

model.add(Convolution2D(16, 7, 7, #border_mode='same',
                        input_shape=X_train.shape[1:]))
model.add(Activation('relu'))

model.add(Convolution2D(32, 5, 5, #border_mode='same',
                        input_shape=X_train.shape[1:]))
model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Convolution2D(32, 7, 7))
model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Convolution2D(64, 7, 7))
model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(4, 4)))
model.add(Dropout(0.5))

model.add(Flatten())
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(nb_classes))
model.add(Activation('softmax'))

[修改于 3 年前 - 2016-11-27 19:26:58]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
4楼

讲一下项目。我方飞行器上载有摄像头,在天空背景下应能够识别出大部分消费无人机,并在操作人员的要求下,跟踪目标飞机,对其进行物理迫降。

那么首先说一下识别无人机到底是在识别什么。我们用肉眼抬头一看,看到有一架无人机在飞,即便看不清楚螺旋桨、电机,我们也知道那是无人机,因为现在是2016年,空中飘过来一个黑点,不是无人机还能是啥,所以我们的肉眼和视觉神经已经习惯了,看到空中有个黑点,黑点的外形不是特别规则,基本就可以确定是无人机。

对于计算机来说也是这样,无人机在空中的图像基本上就是个不太规则的黑点。然而大疆的精灵是白色的,所以这个数据集其实做得不好,白色的无人机图像数量太少,将来要做一个更全的数据集。

按照“传统”CV的做法,要设计几个feature,训练一套classifier。什么东西对“外形不规则的黑点”敏感呢?无人机是有特定的几种外形轮廓的,问题是摄像头装在我方飞行器上不一定稳,平时边缘好识别,抖动模糊的时候就不一定了,最后就是一团糊的,找不到边缘。这次的训练数据集专门加了动态模糊,也是为了应对这种情况。

如果把所有含有飞行器的训练图片,都以飞行器为中心叠加起来,求平均,应该能得到一张小图像,四周是亮的,中间一个深色的圆点。用这张小图对图像进行卷积,求最大值或者二值化,也是一个办法。但是这样一来它就对很多东西不免疫,比如把气球当成无人机,或者大小、亮度变化一下就不灵了。也就是常说的模型太“浅”,不够“深”。

传统方法中比较“深”的是Haar Cascade Classifier。这个算法很多年前就耳熟能详,因此在这之后我会专门针对haar做一个dataset,训练一下看看性能能达到怎样的地步。

后来……后来卷积神经网络将上面这些方法统(qu)一(dai)了。后来斯坦福的教授们都下海了。后来一部分CV研究者被戏称为theorists……以及很多研究生一边欢呼终于不用学理论了一边日复一日痛苦地调着参数

输入图像中的无人机,尺寸从最小到最大相差6倍左右,所以带有pooling的卷积神经网络就成了首选。虽然这是个binary classifier,但是网络规模只比原版cifar-10小一点点(大概100k参数),根据Yoshua Bengio的学习理论,因为深度神经网络太“深”,目标函数太多坑,每一次梯度下降的路径基本不会重叠,参数规模太小(下降路线限制太多)的话很容易过早学进local minima而不是从鞍点溜走,参数规模大一点的话成功收敛概率会高很多。这就类似人的大脑中有很大一部分神经都是闲置的,问题是没有这些闲置的神经,需要学习思考的时候就腾不出地方来了。我之前一直抱着小而美的幻想,把参数数量硬是限制到了9k,结果学10次只有1次能收敛。后来想起Bengio的论文,如梦初醒,把网络调大,其实也没多慢嘛!

另一个训练的奇技淫巧是刚刚发表的 SGDR(自带重启的随机梯度下降法),说白了就是把学习速率按照一个看上去毫无道理的函数来回调节最后收敛速度显著高于一般方法……论文里是这么画的:


原文见 https://arxiv.org/pdf/1608.03983.pdf

我这边的实现效果:


就说这么多吧!对于爱好者来说,当下应该是玩视觉最方便的时代,看上两个月的论文,买张显卡,加上遍地都是的软件包、模型库,一瞬间好像谁都可以顶撞老教授了。

最后,python2的闭包只读,或者必须用dictionary(可写),而python3的闭包要用nonlocal关键字,相比js麻烦不少。所以观众朋友们又发明了Julia语言,继承了Javascript、Lua、python等语言的优秀特性,有兴趣可前往围观。

折叠评论
加载评论中,请稍候...
折叠评论
2016-11-28 05:18:30
5楼
我开始看到以为是要实现的是 detection,提取 bounding box 那种。有点想试试用 HOG+SVM或者LDA做一个sliding window detector 作为baseline看看效果。用 deep learning 实现detection的方法有 https://arxiv.org/abs/1506.01497https://arxiv.org/abs/1506.02640 。最后纯从工程的角度讲,感觉要实现探测空中的无人机这个目标,从相对静止的画面中探测移动物体,比从静止画面中探测静止物体要来得容易,可参考各种成熟的行人探测算法。考虑到 training set是 synthetic 的,建议 testing set 使用自然图片,来评估训练模型对自然图片的generalization效果。

另外刚想到一个收集无人机 bounding box 视频数据的方法:在无人机机身布置不会对外观造成明显影响的红外信标,拍摄时同时使用普通相机和加有滤光片的红外相机。考虑到无人机外形大概就那么几种,分别制作一系列便可。

[修改于 3 年前 - 2016-11-28 08:04:05]

折叠评论
加载评论中,请稍候...
折叠评论
2016-11-29 18:26:36
2016-11-29 18:26:36
6楼
很专业的帖子,赞一个。顺便说一句,法国和荷兰警方是通过训练老鹰来击落无人机的~
折叠评论
加载评论中,请稍候...
折叠评论
2016-11-30 20:56:26
2016-11-30 20:56:26
novakon(作者)
7楼

如果你认真地读完了我上面写的帖子,我目前最新的总结是:classifier可以当detector用,但这不是最优方案。


对网络结构进行一些调整之后,我用1000个epoch、100/batch 把这个数据集跑到了0.9的准确率(期间验证了一点,SGDR确实是可以加速收敛的),考虑到数据集中存在的大量bug(比如全黑背景+全黑的无人机),这个准确率已经很棒了。

但是也遇到一些问题。数据集中用来生成背景的素材图,干扰主要是建筑物,从conv1的feature来看,网络已经学会了怎么从建筑物外墙棋盘般的背景中区分出无人机:


问题是这样效率比较低,比如我要丰富dataset,引入更多类型的背景,那么conv1的feature可能就不够用了,而加大conv1的后果就是……慢。尤其是,人眼在跟踪飞行器的时候,是处于一个在线学习的状态,即便是以前没有见过的无人机,看到在飞之后,就可以学习其外观并保持跟踪;即便是以前没有见过的背景,也应该可以实时适应,在视觉上能够积极地将无人机与背景进行区分(利用相对运动信息)。现在把feature全都做成死的、全都依赖训练数据,在实际环境中工作起来和人脑性能会差很远。所以要设计一个robust的tracker,很可能需要 cnn + lstm + very large real-world dataset,并按照抽象层次进行分阶段训练(从静态图片逐渐过渡到动态、从二维图像过渡到三维场景分析,而不是直接end-to-end)。将来会考虑用blender或者OSG生成这样的dataset。但在这之前,还是先认真刷论文吧。

下图:经过训练的binary classifier,可以通过sliding window的笨方法,在图中大致标记出无人机的所在。cnn输入窗口的宽度是64,因此我每32个像素predict一次,保证窗口之间的重叠,而且比逐个像素slide要快1000倍。图中每个命中的64x64窗口,用一个56x56矩形进行了标记。



(请注意:每个小方格是32x32,predict window是64x64,每滑动32像素predict一次。框线是56x56.)

这其实是这两年ILSVRC做bounding box的主要方法:首先训练一个分类器网络(经过这3年的磨练,大家已经都学会了),然后用滑动窗口方法对图像应用这个分类器(然后对输出还要加一点SVM之类的魔法),以确定object在图中的位置。它们(比如R-CNN及其变种)的特点就是blackbox,naive,simple code,very slow。为了提速,大家提出了很多修修补补又三年的方法,不过始终都显得……不太美观,经常是一堆tricks然后结尾必提我们用多少个百分点的误差换了多少倍的速度……

结果就生产了一大堆大家都很清楚两年之后一定会变成废纸的文章,有点像当年手机厂商张口闭口都是跑分的情况。R-CNN minus R https://arxiv.org/abs/1506.06981 特别阐述了这一点。值得一提的是,他说:


对RPN的态度是Removing。

He Kaiming同学也一连发了几篇文章,表达对R-CNN(及其变体)效果的赞赏以及方法的不敢恭维,在此就不列出了。刚刚读了他的 R-FCN: Object Detection via Region-based Fully Convolutional Networks https://arxiv.org/abs/1605.06409 ,其中提到:


意思就是说,我们做图像分类的那个架构,是希望它对位移不敏感,所以越深、对位移越不敏感的卷积网络效果就越好。而做检测刚好相反,我们需要的结果恰好是对位移敏感的,所以用分类的那个架构来对付检测,就像用扫把洗碗,降低了比赛的观赏性质,对围观群众造成了brain damage。

一个美观优雅高速高效的detector究竟要怎么实现、怎么训练;作为最终产品的tracker要怎么利用detector的训练成果;这些都是接下来需要我去阅读思考的问题。

总结:Zhu Songchun说过,ML解决的仅仅是CV中的实现部分,如果不能确定到底要解决的是什么问题,再快的显卡也不管用。

[修改于 3 年前 - 2016-12-01 02:17:03]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
8楼
引用 Cirno:
我开始看到以为是要实现的是 detection,提取 bounding box 那种。有点想试试用 HOG SVM或者LDA做一个sliding window detector 作为baseline看……
确实是需要做detection,但是苦于没有比较优雅的实现,所以采用了先classifier后detector的naive方法。此处需要更多文献,非常感谢推荐。

这里有一个CNN cascade做的面部识别,作者采用了他能想到的所有提速方法,成果可以直接跑4k视频做人脸检测,演示在youtube有:

https://arxiv.org/pdf/1508.01292v3.pdf

271907

[修改于 3 年前 - 2016-11-30 21:58:34]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-1 00:35:13
9楼
我非常奇怪一点是,为什么你表示从 conv1 的输出能看出 object level 的效果。conv1 只是提取low level的 edge response,如果在存在有复杂背景的情况下,仍然能从 edge response 中清晰分辨出无人机,一个可能的解释是在人工合成训练样本时,没有很好的解决插入的无人机图片与背景图片融合的问题,二者在 illumination 上存在差异,导致结合边缘处不自然,不符合天然图片的像素统计规律。因为没有看到清晰的 response 图片,所以以上仅是猜想。0.9的准确率我认为是过拟合了,这点从 detection 的结果可以验证,因为即使是准确率达不到0.9的 hog sliding Window detector,也可以轻易超越这个效果。还有一点就是 sliding Window 的时候要考虑用 non-maximum suppression 来抑制 shift invariant 的问题。
折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
10楼
引用 Cirno:
我非常奇怪一点是,为什么你表示从 conv1 的输出能看出 object level 的效果。conv1 只是提取low level的 edge response,如果在存在有复杂背景的情况下,仍然能……
conv1(7x7)中有很多网格状的weight,我认为它们对应的是训练样本中大量的建筑物背景。当背景为建筑物,且前景无人机尺寸较小的时候,无人机的外形会和建筑物表面的纹理混在一起(这类样本挺多的,说实话肉眼都不太好识别),要将它们有效地区分开来,cnn就必须能够检测到建筑物表面纹理的不连续,以从中分辨出无人机。

另外0.9仅仅是过拟合了一点点,validation set的命中率达到0.85了。现在的问题不是网络规模太大,而是太小了,然后训练数据是足够的,但是训练目标(binary classifier)和我希望做的最终任务不符(我修改了上面的帖子,增加了另一篇黑R-CNN以及类似detection方法的文章)。我会根据最近的阅读成果,重做dataset,并调整训练目标。

另外:我提供的两张detection示范图片,每个框的绘制方法,是当前像素值+20,所以如果两个框的边缘重叠,那条边会显得亮一点。两张图中无人机所在的位置,都处在多个框重叠的中心,从结果上应该说是成功的。

或者我改成实心填充,这样就更方便看了:

271910

271909

271908


this should work for a drone jammer...

[修改于 3 年前 - 2016-12-01 01:58:57]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-2 22:26:10
2016-12-2 22:26:10
novakon(作者)
11楼
一些更新

前两天Google推出了windows版的tensorflow,现在大家可以在windows上玩tensorflow了。我用tensorflow的原因是它资源很丰富、背景很雄厚。用keras的原因是简单爽快可扩展,用python的原因是这个语言对tensor(高维矩阵)进行操作非常直观方便。


简单介绍一下windows版tensorflow的安装过程:

  1. 首先你会需要python以及numpy scipy blas lapack mkl 等一系列library,可以说对于不熟悉linux和python世界的同学来说这就是个噩梦,对于熟悉的来说是半个噩梦,所以我最后还是安装了Anaconda3(Python3集成环境)大礼包,从官网下载的python3没有Anaconda方便。注意,最新的TF在windows上只支持python3.
  2. 然后从Pypi( https://pypi.python.org/pypi/tensorflow )上下载tensorflow的最新whl包。下载前请注意,分CPU和GPU两个版本。
  3. 如果你下载的是GPU版,请下载安装CUDA和cuDNN。如果不安装,GPU版tf启动时会提示找不到几个dll。
  4. 运行 pip install <下载的whl包文件名>
  5. ……然后在python里面 import tensorflow as tf 应该就可以了。

如果需要用Keras框架,不要用pip install,检测到系统为windows之后会傻傻地跑去下载theano(因为以前tensorflow是没有windows版本的)。我直接从github拖源码,然后Python setup.py就可以了。到装theano那一步我Ctrl-C了。完美的方案应该是把系统检测代码删掉,让用户自己选择是要tensorflow还是theano。

import keras的时候也会遇到问题,keras检测到windows系统(同时检测不到~/.keras/keras.json文件的话)就自动切到theano后端,由于没装theano也会报错。解决方法是手动改keras源码,我已经向作者提交了pull request(更新:作者没有通过request,有需要自己动手吧)。

CUDA的驱动程序在我这边有点问题,GT640M显卡在tf.Session()的一瞬间会跳出一个错误,提示我的显卡无法弹出,然后把我整个系统卡死。所以我暂时还是在用CPU训练。

[修改于 3 年前 - 2016-12-02 23:00:00]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-3 00:03:18
novakon(作者)
12楼
测试新架构

FCN和R-FCN论文指出,可以直接用全卷积网络(FCN, Fully-Convolutional Network)代替传统的conv-fc架构,这样便可以适应任意尺寸的输入,并且保留了输入图像中所包含的物体位置信息,可以直接根据卷积结果生成heat map和bounding box,省去了耗时的regression步骤。

受到以上论文启发,我也修改了网络架构和训练方法。这是我目前正在训练的架构,左边是输入图像,右边是输出heat map。


这个架构有4个卷积层,其中conv1和conv2的作用是feature卷积,conv3和conv4则是代替传统架构中fc层的作用(!)。

因为使用了3x3和4x4两次pooling,最终输出的3x3heat map,覆盖的大概是原图中心36x36的范围。所以对于每个训练样本,我生成了一张36x36的heat map,将目标所在位置设为1.0,背景设为0.0 ,然后将这张map通过双线性插值,缩小到3x3,作为训练的ground truth。而训练样本中四轴飞行器的几何中心,也都落在图片中央36x36范围内。

那么,要怎么设计loss function呢?我们提供的ground truth取值范围在(0,1);而ReLU网络输出的取值范围是(0,+inf)。所以不能用mean squared error。因为架构特殊,Keras也没有提供我需要的误差函数,只好自己拼凑一个了:

def my_fancy_loss(y_true, y_pred):
    # y_true within (0,1
    # y_pred within (0,+inf
    yt = tf.reshape(y_true,[-1,9]) # flatten
    yp = K.softmax(tf.reshape(y_pred,[-1,9])) # flatten, then softmax
    return 1.0 - K.mean(yp*yt, axis=-1)

代码中K是Keras后端,是tf的一层wrapper。因为Keras没有wrap tf.reshape函数,所以我直接混用了tf。

首先把3x3的预测值y_pred和3x3的ground truthy_true都展平成9维矢量,然后对预测值进行softmax,以将其取值范围压缩到(0,1)。然后将两个矢量逐项相乘,最后取平均,再取反。所以如果要降低误差,就要令逐项相乘的和尽量大。因为前面有softmax的存在,要让逐项相乘的和尽量大,预测值的最大值点就必须和ground truth的最大值点的位置接近,尽管最大值的绝对值可以不同。

为了本次训练,我从网上找了更多的无人机素材,生成了5000张64x64训练样例。考虑到每个人训练目的不同,这次我就不直接发生成好的dataset了,直接发透明的png素材。

[修改于 3 年前 - 2016-12-03 00:32:05]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
13楼
使用上述loss function,SGDR 0.1学习率(等效于0.05),4500样本,100/batch 训练(有乱序,无数据增强),训练误差下降到与验证误差相等需要300epoch左右(记不清了),总耗时6小时。不行我得去买显卡了。

271972


训练效果:我们将3x3的网络输出放大到36x36,并叠加到64x64的样例上。 绿色通道是ground truth(x0.2), 红色通道是prediction(x0.02)。

271971


从结果来看,prediction比ground truth定位还准:ground truth 往往只给出了大方向(泛绿),prediction则准确定位到点(这就是为什么图中红绿分明,而不呈黄色)。输出强度也与目标在背景中的分辨难度成正比,比如说第二行最后一列,虽然ground truth给出了无人机的位置,但由于前景和背景混合得太完美,网络输出的activation几乎为零。

[修改于 3 年前 - 2016-12-03 21:19:10]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
14楼

不过,为什么要训练6个小时?看着loss图像下降得那么平缓,我怀疑是学习率设低了。paper里经常用的0.1学习率是针对paper里面提到的loss设置的,这次我用了自定义的loss,学习率也应该改一下再使用。

于是我把学习率从0.1改成了1,最开始那段收敛加速了10倍,可怜了我宝贵的时间。。。



提一点: 根据Yoshua Bengio教授提出的 https://arxiv.org/abs/1301.4083,带有指导、循序渐进的学习(又称大纲学习, curriculum learning)能使误差函数的梯度相比直接端到端学习变得更加平滑,从而加速学习的过程,极大降低在学习过程中陷入局部最优的概率,对于某些问题则能够极大节省网络容量和训练时间。

我这次设计的heat map学习也体现了这一点:由于使用的误差函数与位置相关,网络很快就能搞明白需要识别的特征有哪些、在哪里,从而极大地加速收敛。这就类似小朋友用手指指着某个物体,问大人那是什么,从而有针对性地学习其特征。换句话讲,如果ImageNet的classification允许通过人工方法将所有的概念在图中指给神经网络看,我认为top-5误差完全可以降低到接近1%,而且也不用跑一遍等几天,而应该是几个小时就好。

[修改于 3 年前 - 2016-12-03 22:04:04]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
15楼

(大多数读者)读到这里一定会感慨,这篇文章黑话太多了,根本就看不懂,谁来写个教程啊!!!!!

说实话,如果你不了解机器学习,能坚持看到这里已经很不错了。所以我决定给看到这里的同学们写点什么。

tensorflow相关教程网上很多,但是新手直接跑去看的话,很有可能会发出跟上面一模一样的抱怨,明明每个字都我都认识,可是连在一起怎么就看不懂了呢……下面我根据我的经验,推荐一个入门机器学习的路线。

  1. 学数学

    最低标准:手绘正弦余弦对数指数的图像以及它们的导数和切线的图像,手绘二元函数(z=x^2+y^2)的图像以及其偏导数和切面的图像。如果做不到,找一个高中数学老师也花不了几千,毕竟比读一次大学要轻松多了

  2. 学编程

    最低标准:写一个程序发给你周围的人,并从他们那里收集10个赞。如果做不到,参加一个培训班也花不了几千,毕竟比读一次大学要轻松多了

  3. 学一点数学和图形编程

    最低标准:用一种编程语言,绘制1的图像。

  4. 学一点数字图像处理

    最低标准:用一种编程语言,计算一张国旗的图片中有多少颗星星。

  5. 学《机器学习》

    最低标准:捏着鼻子把Andrew Ng的《Machine Learning》教程看完,把他提到的实验都做了。不要借助任何框架,直接用你熟悉的编程语言写一遍。

  6. 如果你真的做到了以上几点,你就应该(自动地)开始看论文了。Yann LeCun 和 Yoshua Bengio的论文多翻翻吧。

  7. OK,现在你能看懂大部分黑话了。

[修改于 3 年前 - 2016-12-05 18:40:41]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-4 00:59:40
novakon(作者)
16楼
下一步怎么办?

下一步就应该让模型学会从视频中区分图像的背景和前景(利用相对运动信息)。

现在的模型虽然已经能够识别静态图像中的无人机,但如果无人机的外观跟背景图案太接近,我们的模型表现就很差。但是人眼可以做到,飞机飞到树林后面我们仍然可以通过缝隙跟踪,所以计算机应该也是可以做到的。

在生活实践中我们发现,如果一只鸟停在树上,我们肉眼一般是很难注意到的,因为像树枝这样杂乱的背景,相当于把目标淹没在噪声中了。但是只要这只鸟开始飞行,即便是在树林后面穿过,我们也能注意到它,这是因为肉眼有视觉残留效应,当我们的视线快速掠过树枝跟踪这只鸟的时候,对树枝产生的噪声进行了滑动平均,令鸟的图像变得明显、清晰了。这种视觉残留效应其实是必须的,因为人眼视网膜后的神经结构类似于一个差分压缩算法,输出带宽有限,如果不作滑动平均、让噪声全部都进入大脑,就会挤占真正重要的信息所需的传输带宽,这样就会导致我们的动态视觉非常差。

所以要在复杂背景下跟踪一架无人机,我们需要:

  1. 将注意力集中在图像的某个焦点上,焦点具有一定的移动速度
  2. 对焦点图像作时域滑动平均
  3. 滑动平均结果,进入detector。detector根据检测结果,更新焦点的移动速度。

因此这应该可以利用CNN+LSTM实现,现在关于attention based的机器学习论文其实也挺多的,总之需要大量的阅读。

论文倒是找到一篇,08年的,理论解释得非常好,但是方法都是经典方法。


[修改于 3 年前 - 2016-12-05 18:40:17]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
17楼

我们现在知道:将物体的32x32照片分成10类(CIFAR-10),在机器学习领域属于EASY。人类大脑的视觉处理系统对物体的轮廓和细节敏感,并能够将这些轮廓和细节组成更高级的抽象概念,最终判定物体的类别。于是科学家用CNN函数拟合了大脑的这种视觉处理的过程,所以我们现在获得了非常好的分类器。

但这并不等于我们解决了机器视觉的问题。很多人眼拥有的能力,目前大家手中的神经网络还不具备。

首先,人眼的分辨率是很高的,按照这个分辨率,45度视野下接近于8k视频。那么,假如我们要用CNN方法找到8k视频图像中的一架无人机,我们就必须用卷积核对整张图片进行卷积,而我上面展示的最简单的神经网络,也差不多要对整张图卷积100次。这对计算机来说已经很辛苦了,换成人类的大脑则更是不可能的。

那人眼是怎么做到的呢?人眼虽然分辨率很高,但这个高分辨率仅限于中心非常小的一部分,而四周的分辨率是很低的。

下面是人眼视锥细胞(色觉,高分辨率)和视杆细胞(光感,低分辨率)的密度分布图。


视网膜中心的视锥细胞分布是这样的(左为正常人,右为红绿色盲):


所以当有一架无人机在飞的时候,人眼先利用四周低分辨率的视杆细胞感应到无人机的存在,然后控制眼球四周的肌肉,旋转眼球将光轴指向目标,从而获得目标的高分辨率图像,然后接着对目标再进行分类判定。


(图片都来自维基百科)

这样一来,人脑就可以用非常低的带宽,获得极高分辨率的视觉。所以未来实用的机器视觉应用,根据我的设想应该是这样的:


其次,并不是所有的视觉能力都可以后天学习。

以CIFAR-10为例,里面的很多类别是人造的物体,这些物体回到100年前是没有的,但是今天的人类可以毫无压力地学习他们的外观特征,说明对物体的外观特征的分类能力,是可以通过学习获得的,而不是天生的。但是,人类还有很多视觉能力不是通过后天学习获得的,而是天生就有的。

比如我上面一楼提到的动态视觉能力,就属于天生的。看下面这张图,你能找到两架无人机分别在哪里吗?


很困难,因为我们看的是一张静态图片。假如图像是动态的,我们就可以利用上面一楼提到的动态视觉能力。只要无人机稍微有点晃动,即使我们的视线没有盯着它看,敏感的视杆细胞也能马上感受到亮度的微小变化,从而发现无人机。等到我们把视线中心转过去,就可以利用视觉残留滤波的方法,判断那到底是不是无人机。所以要实现robust的追踪,这些问题都是要解决的。

不过这样一来,我们就得把像CNN这样的开环系统,改成多级反馈系统(类似RNN)。每一级之间如何连接,整个架构怎么训练,仍然需要继续刷论文。而且由于动态视觉能力并不是后天习得的,而是通过无数代自然选择进化留下的,因此直接套用现成的机器学习算法是浪费时间,必须先把Human Vision吃透。

本楼是给对这个问题有兴趣的读者做的一个简单介绍,也欢迎大家提出不同意见。

两架无人机分别在这里:


人眼的分辨率分布:


[修改于 3 年前 - 2016-12-04 23:59:24]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-5 00:34:16
18楼
"Our proposed architecture is related to the
two-streams hypothesis [9], according to which the human visual cortex contains two pathways: the
ventral stream (which performs object recognition) and the dorsal stream (which recognises motion);"
https://papers.nips.cc/paper/5353-two-stream-convolutional-networks-for-action-recognition-in-videos.pdf
折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
19楼

[修改于 3 年前 - 2016-12-05 21:41:17]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-12 16:21:10
2016-12-12 16:21:10
novakon(作者)
20楼
let's do this
这几天比较忙,昨晚专门抽了点时间准备训练样本。无人机实拍的风险其实挺高的,而且要获得ground truth特麻烦,所以我还是用我最熟悉的blender做了个精灵的模型:
272166


有了模型之后就可以建立场景,让飞行器沿着路径飞
272165


渲染效果(未使用动态模糊):
272164


最终的视频是使用了动态模糊的,效果会好一些。

这里先发一个预览,640x360分辨率的。
(浏览器不支持该格式的,请直接下载播放。)
0001-0200_600k_640x360.mp4


输出成什么格式最适合用于机器学习任务呢?PNG?JPEG?hdf5?还是numpy的npy格式?还没想好。

blender场景和模型文件:我这边用的是blender 2.72版,14年10月,是比较早的版本了。blender是开源的3D动画软件,好处是一行代码都不用写,大家可以去blender官网下载。



打开上面这个文件之后,你就可以按照你的需求自由调节各种渲染设置,输出符合你要求的视频文件(或者图像序列)。

272169

[修改于 3 年前 - 2016-12-12 16:28:49]

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
21楼

blender的最大优点是可以用python进行交互。

经过一番google,我写了一组脚本,输出每一帧中无人机的屏幕坐标,作为训练用的ground truth.

get_obj_coord.py

# small helper script for CV+ML trainning ground truth data generation.
# by Qin Yongliang

import bpy
import bpy_extras

# get coordinate of object relative to screen.
def get_obj_coord(object_name):
    target = bpy.data.objects[object_name]
    
    # get object's location relative to world.
    target_loc = target.matrix_world.to_translation()
    
    cam = bpy.data.objects['Camera']
    
    scene = bpy.context.scene

    # relative to screen, where (0,0) represents left bottom of camera frame.
    co2d = bpy_extras.object_utils.world_to_camera_view(scene,cam,target_loc)

    return co2d

# get coordinate of object named 'Drone'.
def get_drone_coord():
    c = get_obj_coord('Drone')
    print('drone at screen coord:',c)
    return c

然后运行下面的脚本:

import get_obj_coord as g
import bpy

scene = bpy.context.scene
fs = scene.frame_start
fe = scene.frame_end

def get_drone_coord_list(startframe,endframe):
    list = []
    for i in range(startframe,endframe):
        scene.frame_set(i)
        c = g.get_drone_coord()
        list.append(c)
    return list
        
file = open("c:/coords.csv", "w")
list = get_drone_coord_list(fs,fe)
file.write('x,y,z\n')
for c in list:
    file.write('{},{},{}\n'.format(c.x,c.y,c.z))

file.close()

效果:

其中x和y是屏幕坐标,(0,0)是取景框左下角,(1,1)是取景框右上角。z是从相机到目标的距离。

折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
22楼
不过,使用default blender engine进行渲染实在是太慢了,960x540开启阴影的话平均一帧要1-2s。
272172

相比之下,这么简单的场景用OpenGL可以轻易地跑到200fps以上。所以这个产生训练数据的方法暂时告一段落。接下来我会尝试:
- blender game engine opengl output
- open scene graph
- deep mind lab

[修改于 3 年前 - 2016-12-12 21:33:51]

折叠评论
加载评论中,请稍候...
折叠评论
2016-12-13 14:33:01
23楼
我在做无人驾驶,基于DNN的车辆行人检测,简单说说方法:

1、Detection和Classification在一个网络里做,是全卷积网络,一路卷积到底,没有全连接层(Pooling还是有的)。需要检测几类物体,就有几个输出。训练目标是图片里对应位置的某物体的coverage(0或1),以及如果coverage为1,就有一个box的坐标用来做regression(如果coverage为0就是don't care)。做inference的时候,要对网络输出结果做clustering,得到最终的bounding box list。类似的结构可以参考https://devblogs.nvidia.com/parallelforall/detectnet-deep-neural-network-object-detection-digits/

2、识别出物体之后要做跟踪,可以同时结合feature tracker和box tracker。feature tracker就是建立卷积金字塔之后找特征点,很传统的算法,box tracker就是对前后帧的bounding box做卡尔曼滤波之类的。

3、Foveal在汽车上很好用,因为主要关注视场中间的物体,至于视场旁边的物体,本来距离就近,down sample之后检测精度也很高。用在无人机检测就比较麻烦,搞不好只能在第一次检测的时候降低一下阈值,抠下来再过一次网络。如果多台无人机满天飞就比较难处理了,多搞几个摄像头吧。
折叠评论
加载评论中,请稍候...
折叠评论
novakon(作者)
24楼
引用 小俊:
我在做无人驾驶,基于DNN的车辆行人检测,简单说说方法:

1、Detection和Classification在一个网络里做,是全卷积网络,一路卷积到底,没有全连接层(Pooling还是有的)。需要……
惊现小俊!
1的方法和我现在用的方法是一样的,全卷积网络。
2这是下一步的工作,这段时间要应付考试。
3谢谢指导!

[修改于 3 年前 - 2016-12-13 16:58:27]

折叠评论
加载评论中,请稍候...
折叠评论
2017-1-22 17:58:05
2017-1-22 17:58:05
25楼
楼主能把数据全部转换成二进制(24bit彩色)的吗,我这里C++读的话有点问题,libjpeg有点大。
折叠评论
加载评论中,请稍候...
折叠评论
26楼
cuda?也就是说只支持nv?歧视amd...
折叠评论
加载评论中,请稍候...
折叠评论
2017-2-16 17:51:12
2017-2-16 17:51:12
27楼
https://github.com/Microsoft/AirSim
微软研究团队2月14日在Github网站上发布了一款基于虚幻引擎的无人机仿真器(AirSim),通过一套名为AirLib的模块集提供传感器、环境、四旋翼机架等一系列数学模型,以及虚幻引擎所提供的动力学模型和图像信息,能够以较小的代价获得大量用于深度学习和人工智能研究的数据。

作者:量子黑洞
链接:https://zhuanlan.zhihu.com/p/25265604
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
折叠评论
加载评论中,请稍候...
折叠评论
2019-4-26 20:22:18
2019-4-26 20:22:18
28楼

请问怎么用imagemagick生成的训练样本啊?可以分享一下代码吗?

折叠评论
加载评论中,请稍候...
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

ID:{{user.uid}}
{{user.username}}
{{user.info.certsName}}
{{user.description}}
{{format("YYYY/MM/DD", user.toc)}}注册,{{fromNow(user.tlv)}}活动
{{submitted?"":"投诉"}}
请选择违规类型:
{{reason.description}}
支持的图片格式:jpg, jpeg, png