新的AIBO!

Sony要出新的AIBO了!本科时第一次做机器人就是用的AIBO,当时Sony因为业绩不佳把AIBO部门砍了,AIBO只能找他们维护不再生产新的了。可以即使现在回头看那个时候的AIBO,也是做的很不错的机器狗。

当时用的AIBO是这样的:

新的AIBO长这样:
还是蛮可爱的。

四足机器人的一大优势是运动控制更容易做到可用,并且可以移动的很快。小狗爬来爬去看起来也很萌。之前Robocup标准平台组比赛就用的AIBO,打起来的时候很激烈,看着蛮容易带入的。

这是之前用AIBO比赛时的情景:

后来换成NAO之后…

新的AIBO硬件更强大,4核的CPU,有独立的用来做SLAM的相机。可以想象在家庭环境里做一些人狗交互也是很有趣的。AIBO没有办法做什么实际的家务,还是以娱乐为主。

新的AIBO,型号ERS-1000不便宜,机器本身$1700多,然后要需要以订阅的方式购买Cloud Service,最便宜的plan也要$22每月。这年头机器狗都有Cloud…

不过看到AIBO回归,还是蛮高兴的,不知道有没有机会玩一玩。

News Link: https://www.sony.net/SonyInfo/News/Press/201711/17-105E/index.html

Crazyflie 2.0 + Flow Deck

Crazyflie是一个小型四旋翼无人机平台。开源并且文档丰富,很适合做相关的研究。最新的型号是Crazyflie 2.0。

整体很小,自然续航时间和载重也有限。具体参数可以参见官网

很多做机器人控制的实验室在用这个平台,于是很容易看到有意思的Demo。比如这个Swarm

还有这个奇怪的控制盒子:

这些精准的控制大多依赖于准确并且贵并且贵的Motion Capture系统。Crazyflie本身Sensor有限,在没有外部反馈的情况下是很难控制的。
不像是大疆那些消费级的无人机,很容易就可以飞的挺好。如果用官方的手机App来飞,想做到悬停就要稳定的给它适合的Thrust,基本上很难。

所以,当官方出了这个Flow Deck的时候,立马买了。据说一发布就卖断货了,除了说明产量小以外,也说明刚需旺盛。

Flow Deck可以为Crazyflie提供简单的位置信息,让它可以在没有外部Motion Capture系统的情况下稳定的悬停。

很明显的可以看见板子上有一个向下的摄像头。Flow也就是指Optical Flow。

这就是小飞机和Flow Deck:

UNADJUSTEDNONRAW_thumb_2b1b

可以用原装的卡电池的架子透出板子的部分,把Flow Deck固定在小飞机下面。仔细看板子上有一个小箭头表明正确的安装方向。

UNADJUSTEDNONRAW_thumb_2b1d

然后需要做的是升级小飞机的固件

这个demo.py可以让crazyflie悬停在0.4米高的位置半分钟


import logging
import time

import cflib.crtp
from cflib.crazyflie.syncCrazyflie import SyncCrazyflie

URI = 'radio://0/80/250k'

# Only output errors from the logging framework
logging.basicConfig(level=logging.ERROR)


if __name__ == '__main__':
    # Initialize the low-level drivers (don't list the debug drivers)
    cflib.crtp.init_drivers(enable_debug_driver=False)

    with SyncCrazyflie(URI) as scf:
        cf = scf.cf

        cf.param.set_value('kalman.resetEstimation', '1')
        time.sleep(0.1)
        cf.param.set_value('kalman.resetEstimation', '0')
        time.sleep(2)

        for y in range(300):
            cf.commander.send_hover_setpoint(0, 0, 0, 0.4)
            time.sleep(0.1)

效果还不错。

Jonas过后

来美国第四个年头了。新泽西这个地方每年都有不小的雪。看雪的心情也从刚来时的兴奋变成了爱恨交织。一片白茫茫是不错的景致,但是想到白茫茫一片之下还有自己的车心情也就复杂起来了。

本来以为今年是一个暖冬。本该是雪花纷飞的圣诞节前后可以穿着单衣出门。所以当知道气象台预报有暴风雪要来的时候,我一开始是怀疑的。天气预报总是这样的小题大作。第一年来的时候,学校常常因为预报有飓风而停课。可是飓风常常失约,又或是还未到地方地就失去了活力。

只有Sandy那次,是准的。那时候住在学校附近。天气已经转凉,整整一周的停热水停电停暖气还真是难捱。所幸的是因为离学校不远。那时候每天早早的起床去实验室,再晚晚的回去。中午学校食堂还有免费的救济餐。

按照惯例,这次的暴风雪也有名字,叫Jonas。似乎是拉丁文,不知道有什么含义。如果不是如预报所说的猛烈,恐怕也没有记住的必要了。

气象台也算是是幸运的,这次他们又说对了。

周六早上起来,外边就一片白茫茫了。门口积的雪已经影响到开门了。

https://goo.gl/photos/k8fgeU24NKViZn5k8

https://goo.gl/photos/ByNS4hcQRPNJRcfYA

从家里往窗外望去,窗前小树上堆起的雪已经很高了。

https://goo.gl/photos/vc46b9nWn2E3xL8d7

可是雪还在一直下。这时我才感觉到天气预报这回又立功了。
果然,一夜之后,前门彻底打不开了。

https://goo.gl/photos/VHRwMV3GU2MdwRLNA

不得已,还得出门铲雪挖车。只好绕道从后门出去。计划要从后面挖出一条小道回到前门,以解前门之围。

后院的情况也不太乐观,之前院子里还有房东家小朋友的玩具小车和一些杂物。看起来它们要重见天日还需要耐心等待了。

https://goo.gl/photos/5rnPpbMwkU6pcGtt8

大多数地方的雪都没过膝盖了。吭哧吭哧地劳作了一段时间,总算是从后院挪动到了停车道上。这才看见了车被埋成了什么样。

https://goo.gl/photos/z1ZSkvNhRJ5hR61b7

要把车给挖出来,这个基本上很难。

https://goo.gl/photos/67zUQVsfGUP6es4R7

挖啊挖,终于挖到前门了。抬头一看,门打不开也是讲道理的。

https://goo.gl/photos/HMGezgjix2zfwtCZ9

https://goo.gl/photos/N1DfHZ9zBJJhSgvn7

之前是台阶的地方已经无迹可寻。没有办法,只有继续挖。
成功的挖开门之后,是这个样子的。

https://goo.gl/photos/2XJCaJ6BKogUuzBk6

从上往下看

https://goo.gl/photos/FDiowu3GnXDsPFkv7

下午和小伙伴们一起在停车道上劳作了两三个小时。
Sandy之后,这下又记住Jonas的大名了。

希望这个冬天快点过去吧。

Cardboard VR

上次开会的时候排队尝试了Google的Cardboard和Oculus,虚拟现实(VR)的体验很真实。于是也不难理解现在VR/AR的火热程度了。Facebook有Oculus,Google有Cardboard,微软有HoloLens,还有Magic Leap的神秘兮兮又牛叉哄哄的演示,也是醉了。大家都看好这个市场,虚拟现实(VR)和增强现实(AR)的市场规模可能会达到1,500亿美元…

为了紧跟社会潮流,果断去大Amazon淘了一个Cardboard来玩,就长这样。
http://www.amazon.com/Pro-Compatible-Instructions-Construction-Experience/dp/B00Q1FITMO

Amazon上有各种Cardboard,大都支持Google Cardboard的Apps。Cardboard主体就一张纸板,还有两个镜片,折了几折就成了前面图上的样子。把你的手机放上去做屏幕就可以体验VR了!

这基本上应该是最经济方便的体验VR的方式了。Cardboard支持很多大屏幕手机,我用的iPhone 6没有问题。用的时候需要凑近镜片去看屏幕。因为近视的关系,我起初比较担心戴着眼镜看不是很方便,实际上把眼镜摘了也看得很清楚。因为其实看到的不是真的3D…屏幕就在眼前不远,不是上千度的近视的话,当然应该看得清楚。

目前各种VR设备面临的一个重要问题是晕动病 (VR motion sickness)。wiki上的对晕动病的解释是:

晕动病或运动病,生活中通常被称为晕车、暈機和晕船,是一种平衡失调的疾病。当人眼所见到的运动与前庭系統感觉到的运动不相符时,就会有昏厥、恶心、食欲减退等症状出现。严重者会呕吐。

这个和有些同学打CS会头晕或者开极品飞车就也能开吐了是相同的原理。可能的一个原因是显示屏的刷新率不够高,我自己用的时候也能不时地感觉到屏幕的刷新率跟不上头的移动。这个时候就会有点“跳戏”的感觉 🙂 据说只有一小部分人是很幸运的天生没有晕动症这个问题的。所以,如何解决这个问题也是VR厂商们面前的一个难题。当然大家也在积极的寻找对策。简单的解决方法据说是喝点酒… 也有研究科学家表示,在画面中增加一个虚拟的鼻子也可以缓解晕动症 ._.

我自己用Cardboard的时候也没有感觉到这个问题,可能是因为看的时间不是很久。毕竟Cardboard只是用来体验VR的,需要用手托住Cardboard来看,不适合长时间的看。不知道是不是iPhone 6屏幕的问题,看的时候感觉画面不是特别的锐利,有一种显示的分辨率不够高的感觉。但是整体的体验还是很赞的。iOS上的VR Apps不如Andriod上的多。在这里推荐几个值得试试的应用。

Google Carboard
这个是Google官方的应用,可以先通过这个应用体验一下基本的功能。其中有一个街景的功能,可以体验站在各个著名景点现场环视四周的感觉。

InMind VR
这是一个VR的游戏,画面不错,挺有代入感。用头部的动作来完成射击任务,时间不长,值得一试。

VRSE
这个App里提供了不少很有意思的VR电影,影片时间长短合适,非常推荐。有些是记录片,有些是软广,但是通过VR来看,都挺有代入感。
类似的App还有:RYOT

暂时就发现这么几个,试试看吧 🙂

补充:

GermBuster
一个非常有趣的游戏,用泡泡攻击细菌。最有趣的是细菌也会吐泡泡攻击你,快被打到的时候3D感特别明显,有种被直接打到脸上的感觉…

[Note] Saliency Detection: A Boolean Map Approach

Saliency应该是翻译为显著性。个人理解显著性检测是得到一张图片上每一个像素点的显著程度的过程。对于这个显著程度,直观的理解就是它在这张图上的重要程度。比如,这些照片里

Bird Diversity 2013

组成鸟的像素应该是比背景的像素更加重要,也就是应该有更高的显著性值。知道了各个像素点的显著性之后,可以用来帮助一系列的更加具体的任务,比如这篇文章里的Eye Fixation的预测,也就是预测在这张图片上人会看哪里。还有显著物体的检测,可以更进一步的做物体检测和识别。

直接描述这篇文章的方法吧。输入是一张图片,输出是一张Saliency Map,表示每一个像素点上的显著性。根据Saliency Map可以进一步的做更佳具体的任务。得到Saliency Map的过程是先得到一组Boolean Maps,然后每一张Boolean Map得到一张Attention Map,对所有的Attention Maps求均值之后做Dilation就得到了Saliency Map。过程很简洁。

假设输入图片有三个颜色通道,随机的选一个颜色取一个阈值。然后据此把图片转成一张0/1的图片,颜色值大于阈值的为1,否则为0。这张0/1的图就是一张Boolean Map。重复这个过程就得到了一组Boolean Maps。Boolean Map如果一块区域和很好的封闭的边缘,那么就有可能是一个显著的物体。所以连着图片边框的区域显著性就会比较低。基于这个假设,把连着图片边框的区域都去掉,然后对全图做归一化,就得到了Attention Map。

没有做过Saliency Detection,欢迎指出各种错误。看到一篇文章引用了这个叫BMS的方法就找来看看。然后就发现作者是一起实习的小伙伴。。

[推荐] 王天珍老师的文章

来自科学网博客,王天珍老师的博文:
视觉研究的前世今生(上)
视觉研究的前世今生(中)
视觉研究的前世今生(下)

虽然很多概念不是很明白,但是感觉非常值得一读。这不是关于Computer Vision的研究,主要讨论是对人类视觉的研究。一开始读起来感觉像是在回顾很久远的时代里人们对人类视觉研究的初步探索,读到最后才惊觉原来人们至今对人类视觉的原理仍然知之甚少。我不觉得CV一定要去模拟生物特性来才能得到好的效果。但是人类视觉毕竟是一个强大复杂的系统,非常的有意思。

看到这些文章就想起来上次CVPR上的关于Professor Tsao的邀请报告,讲到她们对猴脑是如何响应视觉刺激而对猴脑的不同部位的不同刺激又是如何影响到视觉感知的研究。虽然我们的CV算法已经可以在很多视觉任务上面得到很好的结果,但是我们对于人类的视觉系统似乎还是不甚了解啊。

[CV]人脸识别检测数据集

做了一段时间的人脸识别和检测,在这里列一下用过的数据集。基本上,大家近期也都是在这几个数据集上检测自己的算法。网上这方面的总结虽然不少,但是一则有些是多年前的数据,或是规模太小或是链接已经失效,再则是数据集的测试协议定义不明,不尽适合用来和其它方法做比较。

1. Labeled Faces in the Wild:
做人脸识别,准确的说是人脸验证(Face Verification),UMass的LFW估计是最近被用的最多的了,LFW采用的测试协议也已经被几个新的数据集沿用了。人脸验证是指,给定两张人脸的照片,算法需要判断它们是不是来自同一个人。最新的结果(ICCV2013),在限制条件最少的协议下,识别的准确率现在已经高达96%了。[广告^_^] 在限制条件最严的协议下,我们的CVPR2013的结果曾经是最好的。最近被Fisher Vector超过了.. 我们还会回来的…

2. YouTube Faces DB:
YouTube Video Faces也是用来做人脸验证的,和LFW不同的是,在这个数据集下,算法需要判断两段视频里面是不是同一个人。有不少在照片上有效的方法,在视频上未必有效/高效。[广告^_^] 在这个数据集上,我们的最新的结果超过81%,目前还没有看到更高的准确率。

3. FDDB:
FDDB也是UMass的数据集,被用来做人脸检测(Face Detection)。这个数据集比较大,比较有挑战性。而且作者提供了程序用来评估检测结果,所以在这个数据上面比较算法也相对公平。FDDB的一个问题是它的标注是椭圆而不是一般用的长方形,这一点可以会导致检测结果评估不准确。不过因为标准统一,问题倒也不大。[广告^_^] 我们ICCV2013的文章在这个数据上面有不错的结果。

4. The Gallagher Collection Person Dataset:
这也是一个做人脸检测的数据集,是Andrew Gallagher的家庭相册。虽然不是给人脸识别设计的,但是很接近实际应用的场景。很适合用来测试自己的方法。

5. The Annotated Faces in the Wild (AFW) testset:
这还是一个做人脸检测的数据集,随UCI的Xiangxin Zhu在CVPR2012的文章发布。值得注意的是在他们的主页有公开的源代码。虽然人脸检测做了很久,但是效果比较好的,可以在网上方便的得到的检测库除了OpenCV以外并不多见。

6. CMU Dataset:
做人脸检测的数据集,这是一个很有些年头的数据集了,虽然大家最近不常用这个数据,但是这不代表这个老数据集很容易对付。最新的检测算法往往需要比较稠密的取比较复杂的特征,这在这个黑白而且分辨率不高的数据集上未必可行。

7. POS Labeled Faces in the Wild:
这个数据我还没有用过,是最近才发布的一个更大型的LFW。可以用来做人脸识别。看起来很不错的样子。

自己感觉比较好用的数据集就是这些了。
感觉不知道应该写点什么,想来还是写写自己专业相关的内容会比较有趣。

[CV]检测灰色块

遇到一个看起来非常简单的问题:一张图片里面有一些某种颜色的色块,怎么样找到它们?
sample-mask
比较囧的是这个问题的起因。因为图片的标注文件丢了,不得不这么反向做检测来找回这些标注…想想人脸那么麻烦的结构都可以被检测出来,CV对付这种几乎完美的单颜色色块应该是小菜一碟吧。所以,大家虽然感觉反向检测自己处理的图片比较囧,但是完全不觉得这是个问题。同屋的哥们当场表示,他可以在10分钟之内搞定。

他的做法是我们一开始的想法,先按照色块的颜色(RGB: 128,128,128)把图片二值化,由于JPEG压缩,色块可能会有噪声。
sample-mask-binarized

然后我们准备对每行求和,对每列求和,会得到两个“直方图”,然后根据“峰”的位置和宽度就可以知道色块的位置和大小了。这个方法的确可以处理一张图里只有一个色块的情况,但是当图里有多个色块的时候,会出现“峰”的叠加,比如这张图,按行求和之后,由于有并排的色块。直方图就会变成这样:
sample-mask-histogram
这种情况之前这种方法就不好处理了。

结果这个看起来非常简单的问题,我们也折腾了好半天。最后还是得人指点,用连通分量来做,才得以解决。

做法是在二值化的图像上,找到不同的连通块 (Connected component),然后留下比较大的,就是灰色块了。为了处理噪声,当然需要用Gaussian做一做模糊之类的。效果还不错。(彩色色块表示检测出来的灰色色块)

large-sample-mask

large-sample-mask-result

问题总是没有看起来的那么简单。
matlab 代码放到 Github 上了: detect-gray-square

程序设计启示 (摘记)

刚开始看代码大全,真是大部头,不知道毕业之前能不能看完,或者看完的时候有没有毕业…(泪)。应该是还没有看到干货部分,不过对于程序设计里的问题,有很多很好的总结,所以摘录一点在这里。这部分原文是 Design Heuristics,直译应该是“设计启示”,可是我觉得应该算是一些心得。想起来以前在图书馆见过有一本书叫做《软件启示录》,按照当年的习惯,应该看过并且仅看过前言 ^^

罗列一下书上的总结,就不瞎翻译了。

Major Heuristics

  • Find Real-World Objects
  • Form Consistent Abstraction
  • Encapsulate Implementation Details
  • Inherit When Possible
  • Hide Secrets (Information Hiding)
  • Identify Areas Likely to Change
  • Keep Coupling Loose
  • Look for Common Design Patterns

Useful Heuristics

  • Aim For Strong Cohesion
  • Build Hierarchies
  • Formalize Class Contracts
  • Assign Responsibilities
  • Design for Test
  • Avoid Failure
  • Choose Binding Time Consciously
  • Make Central Points of Control
  • Consider Using Brute Force
  • Draw a Diagram
  • Keep Your Design Modular

封装、抽象和解耦合是时时记住的准则。但是我没有系统地学过设计模式,这部分要去补习了。

第二个列表提到了层次 (Hierarchies),最近感觉层次是方法,但是也是问题。有时候是为了解耦,有时候单纯为了处理重复代码,很容易就会增加抽象层次,结果就是代码越写越厚,为了保持各层之间独立,新增加底层功能要暴露给上面的代码需要修改很多地方。深以为是自己做的不对,每次大改完之后会好一些,但是层次的增加似乎真是不可避免。想到最近云风大喷C++的时候说C++会引导程序员增加层次,不知道是不是我现在遇到的情况。

最近这次改代码,尽量做到扁平,最理想的情况其实是各个功能可以独立出来,像EM、聚类这些算法可以随时独立的拿到其他工程里去用,但是除非是大量的用代码生成代码 (刚刚想到,不知道可不可行),否则就得手动处理很多重复代码。所以,我觉得库都要有支持基本类型的结构,可以把float*、int*很方便的、高效地转成它们的基本类,否则如果只需要用到库的一小部分功能就要以库里的类型渗透到所有的代码逻辑里为代价,就太不划算了。

还有一点有同感的就是 Make Central Points of Control 这一点,写实验的时候这一点太重要了。实验里有很多参数、设置都放到一个地方直观而且不容易出错。我之前的做法是非常简单的config类,然后是 key-value 来存取值,但是当配置躲起来的时候,一则 key 太多放在一起很没有逻辑,二则 key 是没有类型的,如果程序里到处都是valueOfKey()这种调用,很容易出错。为了把key-value和对应的模块放到一起,又需要有一些结构做配置之上的封装,形成像em的配置、取特征的配置这类的结构。现在的问题就是,如果要增减一个配置结构里面的内容,需要改动至少两个不同的地方。感觉这个是老问题,应该有现成的解决方法,但还是没有找到。

配置文件的另外一个问题就是需要有东西生成配置文件,现在用bash写configuration文件,然后C++读,所以C++需要和bash共享一部分内容,比如key-value pairs的key。现在的做法是类似用bash读一个config.h。所以bash脚本就必须知道源文件的位置,不知道有没有更好的解决方法。

本来就想写个笔记,没想到吐槽了一大堆。在实验室写代码的好处就是可以自己控制整个工程,虽然工作量大一点,也没有测试帮忙保证质量,但是可以默默地改代码,满足一下码农的完美主义。

Mac远程桌面到Linux服务器

假期结束,回到学校开始干活 :]

为了远程使用Linux服务器,折腾了一个下午。最终看来还是用vnc最简单了。

实验室有两台强劲的Linux服务器用来做研究。之前我一直都是用ssh登到服务器上去码代码,反应速度很快,感觉很不错。但是因为在做机器视觉,难免需要看远程的图片。命令行虽然快,总不能每次都把图片拷贝到本地再看,有时候需要可视化中间结果,ssh也行不通。

当本地机器是Linux系统的时候比较好办。可以用ssh加X forwarding的方法。在本地开一个X,然后把远程服务器的X指令通过ssh转发到本地的X,码代码没有什么延迟,感觉还是很不错的。

sudo X :11 vt11 2>&1 >/dev/null &

这样可以在本地新开一个X,Ubuntu下用Ctrl+Alt+F11可以切到第11个虚拟终端

回到之前的终端,开ssh和xterm

xterm -display :11 -e ssh -X server-host &

然后可以切换到第11个虚拟终端来使用远程Linux服务器上的X了。

这样虽然好,但是要求本地机器上有安装X。在Windows和MacOS下虽然有解决方法,但是比较麻烦。

用VNC的话就没有这个问题,毕竟VNC的客户端是很容易找的。

当然需要先ssh登录到Linux服务器上安装vncserver

sudo apt-get install vnc4server

然后启动vncserver

vncserver

这样就搞定了。

在本地的Mac下可以用自带的Screen Sharing App或者著名的Chicken of the VNC连接到server-host:5901来查看和控制远程Linux桌面。

在服务器上启动了vncserver之后,可以通过修改

~/.vnc/xstartup

这个文件,来指定远程的X启动之后要执行什么命令。我喜欢用openbox,所以我的xstartup文件就是这样子

#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
openbox-session&
#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#x-window-manager &

另外,在启动vncserver的时候可以使用参数修改远程桌面的分辨率

vncserver  -geometry 1280x1024

这么一来就可以在命令行下写代码,同时再开一个vnc窗口看图,感觉不错!

这篇文章有列举一些远程到Linux服务器上的其它解决方法,如果有服务器的root用户权限的话,freeNX貌似也是一个不错的选项。