0
我妻子几乎每天都会问这个问题:我今天该穿什么?这是一个很难回答的问题,因为首先我没有时尚感,而 Yumi 恰恰相反,她有时装设计学位。其次,我记性不好,我想不起来她过去几周穿了什么衣服,回答可能千篇一律。
所以,有一天,我决定利用周末的时间来开发一种我认为可以解决她的问题的技术。
在开始之前,我想感谢她在这个项目和我所有其他疯狂的项目中给予的所有支持。亲爱的,你是最棒的!
研究
我开始做一些研究,找出我需要建立什么样的模型。我试着把自己当成她,找出我需要什么样的信息来决定今天穿什么衣服。
我有什么衣服?(CH)
显然,我需要从我现在拥有的衣服中推荐一件衣服。所以我认为这是一个必须要有的信息。
过去几周我穿了什么?(CD)
你肯定不想连续几天一次又一次地穿同样的衣服。尽管这并不是非常关键,但知道自己在过去几周里穿了些什么,对于提供更多样的推荐还是很有用的。除此之外,知道关于天气和今天要做什么对推荐系统也很有用,你需要知道哪件衣服适合哪种场合和天气。
今天的天气(W)
不用担心你穿的衣服会受到那天天气的影响。
事件(E)
当你要去参加一个聚会时,你可能想穿一件好看淑女的衣服,但是如果你要去远足,你会想穿一件适合运动的衣服。
综上所述,今天要穿的衣服(CTWT)可以用以下函数来描述:
CTWT = Func(CH, CD, W, E)
我只需要建立一个系统来实现这样的函数,听起来很简单吧?我开始疯狂地发挥想象力,最后决定做一个语音助理设备,上面会有一块屏幕,Yumi 可以问「我今天应该穿什么?」屏幕上就会附上推荐服装的照片。甚至是,它将显示 Yumi 穿那些衣服的样子,以提供直观的选择。这个设备还能够解释它做出这种建议的理由,这样它就可以回答 Yumi 的后续问题「你为什么推荐我这样穿?」。
这项技术肯定会涉及很多人工智能。兴奋之余,我开始为这个人工智能寻找一个名字和一个角色,并最终决定命名为 faAi。它的发音是「Fei」,代表人工智能时尚助理。
行动计划
我开始记下我需要执行的任务:
建立一个照片日记,记录她每天穿什么(CD),标记事件和天气。
建立她自己的服装照片目录(CH)
在她的衣柜上安装一个语音助手机器人
制作服装目录的一个简单方法是将她所有的衣服逐一拍照。她会每天自拍。然而,为了客户体验和自动化,将这个过程自动化对我来说是不可拒绝的。我需要一个系统,自动建立她的服装目录和穿搭日记,而不需要她自己动手。
经过一番思考,我想出了这个计划:如果我在房子里的某个地方安装摄像头,自动拍下她全身的照片会怎么样?
相机应该足够智能,只给她拍张照片,而不会拍下我、我父母和别的亲戚。它还需要能够识别她穿的衣服,将它们存储在衣服日记中,并且将每件衣服存储在对应的衣服目录中。
除了相机,我还需要一个计算设备来执行以上所有的智能操作。完美满足要求的设备是 AWS DeepLens。这是一个支持深度学习的摄像头,你可以在设备上部署无数的人工智能模型。
从这一点开始,我开始意识到这将是一个大项目。我肯定需要建立一个人工智能模型,在视频帧中识别人脸和身体,并进行面部识别。在 Yumi 的脸被识别之后,下一个人工智能模型需要识别她的衣服,并执行搜索,如果我们没有在她的目录中添加这件衣服,那就创建一个新条目。不管怎样,如果这是一件新衣服,一个条目也会被添加到衣服日记中,并标记对应的天气和事件。
为了保持头脑清醒,我决定将这个项目分成几个阶段,第一阶段的重点是自动构建衣服日记。因为我不需要建立服装目录,我还不需要建立服装识别系统。尽管最终目标是在她的衣柜上加上一个语音助理,但我希望在第一阶段完成时她已经可以使用一些功能。所以,我增加了一个额外的任务,建立一个移动应用程序,她可以用这个程序来浏览她的衣服日记,这至少可以帮助她决定穿什么。
服装日记自动生成器
我的第一个任务是找到安装这台相机的位置。把相机装在她的衣柜里可能不是个好主意,因为我真的不想意外地曝光不合适的照片。另外,我只想在她外出时把这些衣服加到她的日记里,没有必要记录她在家里穿着睡衣的样子。
经过一番搜寻,我找到了一个完美的地点。在一个柜子上,可以直接看到家的大门。好吧,你需要穿过大门才能离开房子。
用 AWS DeepLens 检测人和人脸
我的下一个任务是建立一个运行在我的 AWS DeepLens 中的人工智能目标检测模型,它可以检测人和脸的存在和位置,用面部识别检测出他们是谁,然后将他们全身的图像裁剪到衣服日记中。
我使用 Amazon SageMaker 构建了一个自定义的对象检测模型,并将其部署到 AWS DeepLens 中。不过这里就不赘述细节了,我将在一个单独的博客中公布全部细节。
在 AWS DeepLens 上运行的人脸和目标检测
AWS DeepLens 提供了一个名为 Project Stream 的非常有用的特性,可以在其中显示和注释视频帧,并在你的 web 浏览器上观看它们。这样,我可以很容易地观察我的模型的性能,并绘制一些文本和框来帮助我调试。正如你在上图中看到的,我的模型正准确地辨认出 Yumi 的全身和脸部。我对准确度很满意。
在正确的位置检测到人
下一个要解决的问题是,只有当人靠近门区域时才触发拍照,这通常发生在有人打算离开房子的情况下。然而,下面的一段视频显示了一个假阳性检测,这个人只是从前客厅走向餐厅。
假阳性检测
看看下面我的房子平面图,可以清楚地看到两个红色箭头,这两个箭头指示的是导致假阳性检测的人的行走路径。而我们只想抓住在绿色区域的人。最简单的解决方案是,只有当一个人的边界框的顶部和底部完全位于屏幕内部时,才拍下他。使用上述假阳性情况测试此逻辑将正确跳过此图像,因为边界框的底部在屏幕之外。
当边框的顶部和底部都完全位于屏幕内部时,将触发正确的图像捕获。
正确检测
为了确保我已经覆盖了所有可能的假阳性情况,我需要运行一整天的系统。首先,我必须完成系统的下一部分,它将检测到的人的裁剪图像发送到我的图像记录器 s3 存储器中。这样我就可以在没有监督的情况下运行系统一整天,并且在试运行结束时简单地检查该存储器中的所有图像。
从物联网设备发送图像的最佳方式是通过 MQTT 消息传递系统,这是非常容易做到的,特别是在你创建 AWS DeepLens 项目时已经提供了很好的示例代码。我只需要添加一些额外的代码行,将裁剪后的图像编码为 jpeg 流,并对它们进行 base64 编码,这样我就可以通过 MQTT 将其作为字符串消息发送。
client = greengrasssdk.client('iot-data')
iotTopic = '$aws/things/{}/infer'.format( os.environ['AWS_IOT_THING_NAME'])
personImageRaw = cv2.imencode('.jpg', personImage)[1]
personImageStr = base64.b64encode(personImageRaw)
client.publish(topic=iotTopic, payload=personImageStr)
消息将由云中的 MQTT 主题订阅者接收,然后触发 lambda 函数以 base64 解码图像并将其保存到 s3 存储器中。从 MQTT 字符串解码图像非常简单,只需下面的一行代码。
jpgStream = base64.b64decode(event
有了以上这些,我一整天都在运行这个系统,周末过得很愉快。
排除岳母
在运行了一整天的系统之后,我的图像记录器显示了很多有趣的图像。一些图像是正确的检测,如下所示,这是好的。
正确检测
看到我的其他家庭成员被记录在案是意料之中的事,然而其他的事情引起了我的注意。在所有拍摄的照片中,95% 都是我岳母(更具体地说是她的上半身)的照片。
岳母正在做她的传统饺子
查看下面的原始视频片段日志,可以发现原因。
坐在厨房长凳后面的岳母
显然,她通过了检测逻辑,因为她的人的顶部和底部(由于与厨房长凳的遮挡,只检测到一半的身体)完全在屏幕内。她花了很多时间在厨房里,这个系统捕捉了她的很多照片。这会导致这个过程进一步走下轨道,做很多不必要的面部识别,这是不好的。然而,看到她一整天被记录下来的无数照片,让我想起她每天都在忙着为我们准备饭菜和帮助我们带宝宝。对我来说她是世界上最好的岳母…
好吧,不管她有多棒,我不希望她的照片在处理过程中占据主导地位。这个问题只需引入一个禁区就可以解决。其目的是排除排除线左侧的检测(如下红线所示)。
排除婆婆的区域
再运行一整天的系统,就发现不会有婆婆坐在厨房的长凳后面的照片了!
检测到正确的人
我的下一个挑战是添加一个面部识别模块,只记录 Yumi 或我自己的图像。澄清一下,不是说我需要用这个系统来推荐我穿什么衣服,而是为了让我自己可以轻松地测试这个系统,而不必让她一直在镜头前摆姿势。
我真的很想在边缘做面部识别,以节省成本。不过,经过进一步调查,这似乎很难。一个合适的面部识别系统是相当 GPU 密集的,这将为一个已经很慢的系统增加一个重要的处理时间。目前,我的面部/人检测系统以每秒 1 帧的速度运行。任何比这慢的速度都会降低抓拍成功的几率。像这里描述的一个简单的面部识别系统对我来说不起作用,因为它只能识别一个直接的正面人脸。
基于以上这些原因,我决定在云中做面部识别。我设置了另一个 lambda 函数,当我的图像记录器中有一个新条目时,该函数将被触发。这个 lambda 函数被称为 AWS Rekognition——通过面部识别来识别人(Facial Recognition to identify the person)。如果确定此人是我或 Yumi,将创建 Postgres 数据库条目。这个 Postgres 数据库就是我们一直在谈论的服装日记。拍摄图像时的时间、温度和天气状况(晴天、下雨、多云)以及确定的人员姓名也作为条目的一部分存储。目前的温度和天气是通过向气象局打一个 RSS 电话获得的。最后,图像还将被复制到另一个 s3 存储器中,该存储器充当公共图像服务器,我的移动应用程序可以访问该服务器。这样我就可以确保只有满足条件的图像集是公开的,而且将来我甚至可以添加额外的检查来确保公开的图像中没有敏感的图像。
使用 AWS 识别——面部识别是相当直接的。我只需要创建一个包含我想让系统识别的人的人脸集合。对于每个人脸(我和 Yumi),我需要调用 IndexFace 将它们添加到集合中。检查一个面是否在集合中就像只调用一个 api 一样简单。
打造时尚日记应用
这是第一阶段中最激动人心的部分,因为最后我将能够在移动应用程序上可视化服装日记。我们都是 iphone 用户,所以移动应用程序必须在 iphone 上运行。现在有很多方法来构建移动应用程序,比如使用像 PhoneGap 这样的 html5 框架,像 Ionic 和 Xamarin 这样的交叉开发框架,或者直接使用 Xcode。不过,由于过去我是一个 iOS 开发人员,因此显然我的选择是 Xcode。
为了提供对 Postgres 衣服日记的访问,我使用 lambda 函数构建了一个公共 REST API。用它构建一个功能性 REST API 实在是太容易了,以至于我对此印象深刻。通常,你将花费大部分开发时间处理基础设施和部署,例如编写 REST 应用程序框架、URL 路由、部署脚本等,而不是编写实际的 API 代码。如果你需要编写的 API 像我的例子中那样简单,那么它就更普遍了。
最后,下面是整个端到端架构图。
faAi 架构图
我设法在一天内完成了应用程序和 REST API,包括设计应用程序启动屏幕和图标。如下图所示,应用程序的界面非常直观:一个可滚动的垂直列表,显示按日期分组的 Yumi 的图像、天气(下雨,多云或晴天)图标、一天的温度等。我现在可以说系统已经开发完成了!作为一个有经验的软件开发人员,我知道下一个重要的步骤是 QA。
faAi 应用程序
QA
我整个星期都在运行这个系统,看起来它工作正常。我拍到了尤米进出房子的照片,没有一个假阳性!我还在她的手机上安装了这个应用程序,这样她就可以开始使用它并给我反馈。
尽管取得了很好的成绩,但在下一阶段我还需要改进和补充一些东西。
更好的姿态检测
一半的图像是以非理想姿势拍摄的。例如,当她走到换鞋长凳前,抱着我们的孩子,或者穿着一件夹克,上面盖着她实际穿的衣服,一条腿向上笨拙地侧身时。我还发现了一些例子,她有时并不是准备出门,而是穿着睡衣站在门前。faAi 还不是很聪明,只要它检测到一张脸,不管姿势的质量如何,它都会拍照。
faAi 抓拍到的非理想姿势
对于这个阶段来说,这并不是什么大不了的事情,因为我们的目标是开发一个移动应用程序,让她可以浏览服装日志。她能很容易地过滤掉其他坏姿势或不相关的照片。为了解决这个问题,需要一个更复杂的系统,我将在未来的阶段尝试。目前,最简单的解决办法是让她脱掉外套,面对镜头,在出门或进屋时迅速摆好姿势,这样拍的前几张照片就很好了。
事件检测
这是我在这一阶段没有时间完成的任务,我将在下一阶段处理。知道她出门的原因也有助于过滤掉不需要的抓拍,例如:她出去扔垃圾的时候。
现在就这样了,我很高兴达到了一个里程碑,但是还有很多挑战需要我去解决,解决所有问题之后才能有一个完整的端到端系统。但是没有挑战的生活有什么意思呢?
请继续关注下一阶段!
雷锋网雷锋网雷锋网
雷峰网版权文章,未经授权禁止转载。详情见转载须知。