如果你也答不出妻子「我今天穿什么合适」的提问,现在 AI 能帮你解围了。澳大利亚 Carsales 公司 AI 负责人 Agustinus Nalwan 近日发布文章介绍了他为妻子创建 AI 穿衣推荐系统的经历。目前他已经完成了这套系统的第一阶段,构建了一个穿着日记记录系统(包含人体检测和人脸识别)和查阅该日记的 iPhone 应用。这大概就是极客的浪漫吧。
faAi,时尚助理人工智能
我的妻子几乎每天都会问一个问题:
今天应该穿什么?
这个问题很难回答,因为第一我对时尚无感,而 Yumi 则刚好相反,她拥有一个时装设计学位。第二,我记不住过去几周她穿过什么衣服,所以没法提供多样化的答案。
今天我该穿啥?
所以,某天我觉得花个周末,构建一个我认为可以解决这个问题的技术。
在我开始介绍这个项目之前,首先我要感谢她给予我这个项目和其它所有疯狂项目的支持。亲爱的,你最棒!
研究
首先我做了一些调查研究,以了解我需要做什么。我尝试从她的角度思考我究竟需要什么信息才能做出「今天穿什么」的决定。
我有什么衣服?(CH)
很显然,我需要从已有的衣物清单中进行推荐。所以我觉得这是必不可少的信息。
过去几周我穿过什么?(CD)
当然,你可不想一连几天一遍又一遍地穿同样的衣服。即使这并不是特别关键,但知道过去几周你穿过的衣服有助于实现推荐结果的多样化。在此基础上,穿不同衣服时的天气和事件信息也对推荐很有用,因为这能让推荐系统知道哪些衣服适合当前的场景和天气。
当日天气(W)
不用说,你的穿戴肯定会受当前天气影响的。
事件(E)
当你参加聚会时,你会想穿得花哨一些,比如穿件裙子;但是如果你要去远足,你可以就要穿些适合运动的衣物。
归总起来,「今天穿什么(CTWT)」问题可用以下函数描述:
CTWT = Func(CH, CD, W, E)
我需要做的就是打造一个能执行这个函数的系统。听起来很简单吧?我开始放飞自己的想象力,最终想到了一种安装在衣柜上的带有屏幕的语音助理;她可以询问「今天我该穿什么?」这个系统会用推荐衣服的照片作答。不仅如此,它还会展示她穿这件衣服时的样子,从而提供更多视觉信息。它还能解释推荐这件衣服的理由。为什么?所以它也能回答 Yumi 在我给出建议后接下来的问题「为什么你推荐我穿这个?」
这个系统肯定会涉及到很多 AI。我很激动,我首先想为这个 AI 系统想一个名字,然后想出了 faAi,读作「菲」,代表「Fashion Assistant Artificial Intelligence(时尚助理人工智能)」。
faAi
行动计划
首先确定我需要执行的任务:
- 构建一个她每日穿着的照片日记(CD),标记上事件和天气
- 构建一个她拥有的衣服的照片目录(CH)
- 构建一个语音助理 bot,并将它安装到她的衣柜上
我可以通过给她的所有衣服逐一拍照来构建衣服目录。而穿着日记则可通过每日自拍来获取。但是,作为客户体验和自动化的倡导者,我可不会这么做。我需要构建一个能毫不费力地自动构建衣服目录和日记的系统。
经过一番思索,我想出了这个计划。我可以在家里某处安装一个照相机,自动拍摄她的全身照。这个相机需要足够智能,只拍摄她一个人的照片,不会拍我或我的父母或岳父母(是的,你可能想知道为什么,我的父母和岳父母时不时地会与我们同住,幸运的是他们能很好地相处)。它还要能识别她所穿的衣服,并将这些衣服存储到穿着日记中,并且仅将之前没有记录的衣服保存到衣服目录中。
除了相机之外,我还需要一个计算设备来执行上面所有的智能计算。AWS DeepLens 是完美的选择。这是一款具备深度学习能力的相机,让你可直接在设备(边缘)上部署很多 AI 模型。
AWS DeepLens
现在我开始意识到这会是个大项目。我肯定需要构建一个能找到视频帧中的脸和人体以及执行人脸识别的 AI 模型。如果认出了 Yumi 的脸,那么接下来的 AI 模型就需要获取她的穿着信息并执行一次搜索:是否已经将该衣物加入到了衣服目录中。如果没有加入,就新建一个条目。不管是不是新的穿着,都会向穿着日记添加一项,并标记上天气和事件。
为了保证条理清楚,我决定分多个阶段完成这个项目。第一个阶段仅专注于自动构建穿着日记。因为现在还不需要构建衣服目录,所以还不需要构建衣服识别系统。尽管最终目标是在她的衣柜上装一个语音助手,但现在我想做一个在第一阶段完成后就能使用的东西。所以,我增加了一个额外任务:构建一个她能用于浏览自己的穿着日记的移动应用,从而能为她的穿衣决定提供最低程度的协助。
自动穿着日记构建器
我的首个任务是找个地方安装相机。把相机装在衣柜上其实并不好,因为我可不想意外拍到我不应该拍摄的照片。你懂我的意思。此外,我只想将她外出时穿的衣服加到穿着日记中。没必要记录她穿着睡衣在屋里走动的样子。
经过一番搜索,我找到了完美的位置。在一个橱柜上面,直对大门。毕竟,你需要经过大门才能出去。
AWS DeepLens 安装位置
使用 AWS DeepLens 检测人体和人脸
我的下一个任务是构建一个 AI 目标检测模型并在我的 AWS DeepLens 中运行,这能检测人体和人脸是否存在以及位置。人脸是用于识别人的身份,人体检测则是为了裁剪出全身图像以便存入穿着日记。我使用 Amazon SageMaker 构建了一个定制的目标检测模型,并将其部署到了 AWS DeepLens 中。但是这篇博文着眼于介绍更高层面的设计,全面的细节我将用另一篇博文来介绍。
运行在 AWS DeepLens 上的人脸和人体目标检测,Project Stream 窗口给出了一些调试标注
AWS DeepLens 带有一个非常强大的功能 Project Stream,可以展示和标注视频帧,你可以在网络浏览器查看它们。通过这种方式,我可以轻松地观察我的模型的表现以及涂绘一些文本和线框来辅助我进行调试。你可以在上图中看到,我的模型能够准确地识别 Yumi 的整个身体和脸。这个准确度很让人满意。
在合适的位置检测人
下一个要解决的问题是仅在大门区域有人时才触发拍照,因为这可能说明有人可能出门。同时,下面的示例录像表明也可能出现误报检测:此时人只是经过门前从客厅去餐厅。
误报检测
看看下面我家房子的平面图,其中的两个红色箭头指示了会导致误报检测的人员行走路径。而我们只想获取人在绿色区域时的照片。针对这个问题,最简单的解决方案是只有当人上半部分和下半部分的边界框都完全在屏幕内时才拍摄照片。使用这个逻辑来检测上面的误报可以成功跳过这张图像,因为这个边界框的下半部分在屏幕之外。
而下面的正例会触发正确的图像获取,因为其边界框的上下部分都完全在屏幕内。
正确的检测
为了确保已涵盖了所有可能的正例和负例情况,我需要运行这个系统一整天。首先,我必须完成该系统接下来的部分,它可将检测到的人的裁剪图像发送给我的 Image Logger S3 bucket。通过这种方式,我可以运行系统一整天而无需我的监督,然后在试运行结束后再检查 bucket 内的所有图像即可。
将图片送出 IoT 设备的最佳方法是通过 MQTT 消息系统,操作起来极其简单,而且在创建 AWS DeepLens 项目时还提供了很好的示例代码。我只需要额外添加几行代码将裁剪后的图像编码成 jpeg 流并用 base64 编码它们,以便我可以通过 MQTT 以字符串流的形式发送它们。
代码语言:javascript复制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 bucket。从 MQTT 字符串解码图像非常简单,只需下面一行代码。
代码语言:javascript复制jpgStream = base64.b64decode(event)
以上步骤就绪之后,我运行了这个系统一整天,并愉快地度过了周末接下来的时间。
规避岳母
在运行了系统一整天之后,我的 Image Logger 展示了大量有趣的图像。某些图像是正确的检测结果,如下图所示。结果良好。
正例检测
可以预期能检测到我的其他家人,但是我注意到一些其它事情。其中有大量我的岳母的图像(更确切的说是她的身体上部分),占到了所有获取到的图像的 95%。
岳母在包传说级的饺子
查看如下所示的原始视频的录像后,解释了原因。
岳母在厨房的工作台后
很显然,她通过了检测逻辑,因为她个人的边界框(由于厨房工作台的遮挡,仅包含一半身体)的上下部分完全位于屏幕内。这个系统获取了大量她的照片,是因为她在厨房花了大量时间。这会导致这个过程进一步减慢,因为这会需要大量不必要的人脸识别,这可不好。但是,看到她这一整天被记录下来的无数照片,让我知道她每天为我们做饭和照顾我们的孩子是多么的忙。对我来说,她是世界上最好的岳母。
好吧,尽管她很好,但我并不希望她的照片主导后续的工作流程。这个问题很好解决,只要引入一个排除区域即可,即不检测排除线左侧的部分(如下图的红线所示)。
岳母规避区域
再次运行这个系统一整天,不会再出现厨房工作台之后的岳母了!
检测正确的人
我的下一个难题是添加人脸识别并且只记录 Yumi 或我自己的图像。说明一下,我需要使用这个系统不是为了给我自己推荐要穿的衣服,而是以便我自己轻松地测试这个系统,不必老是烦扰她在相机面前摆造型。
我确实希望能在边缘完成人脸识别,以便节省成本。但是,经过进一步的研究之后,这似乎非常困难。可行的人脸识别系统需要大量 GPU 计算,这会为原本就慢的系统平添大量处理时间。目前我的人脸/人体检测系统的运行速度是 1 FPS。再慢就难获得好照片了。https://aws.amazon.com/deeplens/community-projects/OneEye/ 这样的更简单的人脸识别系统对我来说效果不行,因为它只能识别正面正脸。
考虑到以上问题,我决定在云上执行人脸识别。我设置了另一个 lambda 函数,当我的 Image Logger 有新项目时就会触发。然后,这个 lambda 函数会调用 AWS Rekognition 的人脸识别。如果这个人的身份被确定为我本人或 Yumi,则创建一个 Postgres 数据库条目。这个 Postgres 数据库就是我们一直在谈的穿着日记。图像获取时的时间、温度和天气情况(晴、雨、阴)以及识别出的人的名字也会被存储为该条目的一部分。当前的温度和天气是通过 RSS 调用气象局的数据获取的。最后,这张图像会被复制到另一个 S3 bucket,其用作可通过我的移动应用访问的公共图像服务器。这样,我能确保仅有受限的图像是可公开访问的,未来我甚至可以添加额外的检查以确保不会公开任何敏感图像。
使用 AWS Rekognition 的人脸识别很简单直接。只需要创建一个我想要系统识别的人脸的集合即可。对于每张人脸(我和 Yumi 的),我需要调用 IndexFace 以将它们添加到该集合中。
- 更多详情请参阅:https://docs.aws.amazon.com/rekognition/latest/dg/API_IndexFaces.html
- 检查一张人脸是否在该集合中也很简单,只需一次 API 调用:https://docs.aws.amazon.com/rekognition/latest/dg/faces-detect-images.html
构建一个时尚日记应用
这是第一阶段最激动人心的部分,因为我终于可以在一个移动应用上查看穿着日记了。我和妻子都是 iPhone 用户,所以这个移动应用必须要在 iPhone 上工作。如今构建移动应用的方法非常多,比如使用 PhoneGap 等 HTML5 框架、使用 Ionic 和 Xamarin 等交叉开发框架、直接使用 XCode。但是,毕竟我过去也是一个 iOS 开发者,所以很显然我的选择是 XCode。
为了访问我的 Postgres 穿着日记,我使用一个 lambda 函数构建了一个公共 REST API。这个过程非常简单,我都惊呆了。传统上,你需要花费大部分开发时间来处理基础设施和部署,比如编写 REST 应用程序框架、URL 路由、部署脚本等等,而不是写真正的 API 代码。如果你需要写的 API 和我的一样简单,那么这种情况会更加普遍。
最后,下面是整体的端到端的架构示意图。
faAi 架构示意图
我成功在一天之内完成了应用和 REST API 的开发,包括设计应用程序启动屏幕和图标。这个应用的界面如下所示,很直观。其中有一个可滚动的竖直列表,展示了记录下来的 Yumi 的图像,并按日期进行了分组。另外还有一个天气图标(雨、阴或晴),再点一下则会显示当天的温度。现在我可以说这个系统已经开发完成!作为一名见过世面的软件开发者,我知道下一步是 QA(质量保证)。
faAi 应用程序
QA
我运行了这个系统一周时间,看起来能够正确工作。我拍到了 Yumi 进出门时的照片,而且没有一张是假正例!我也在她的手机上安装了应用,这样她就可以开始使用它并为我提供反馈了。
尽管结果不错,但还是有一些需要我改进的和在下一阶段添加的地方。
更好的姿势检测
获得的图像中半数的姿势都不够理想,比如在她去够换鞋台时脸朝向了一边而且一条腿抬了起来、抱着我们的孩子或穿了一件外套遮挡了她实际穿的衣服。我还找到了一些实例是她并不是想出门,而是穿着睡衣站在门前。faAi 还不够聪明,只会在检测到人脸时拍摄照片,而不管姿势质量如何。
faAi 获取到的不理想的姿势
在这个阶段这不是什么大问题,因为现在我们的目标是让她能在手机上浏览自己的穿着日记。她自己就能轻松地区分姿势不佳的照片和无关照片。为了正确解决这个问题,我需要更复杂的系统。我会在后面的阶段尝试。目前最简单的方法是让她在出门或进门时脱去外套,面对相机,快速摆出一个好姿势,使得一开始能拍出几张好照片。
事件检测
这个阶段我还没有时间完成这项任务,我将在下一个阶段解决它。知道她出门的原因事件也有助于滤除不想要的照片,比如她只是出门丢个垃圾。
就目前而言,我很高兴完成了一个里程碑。但是,要创造一个完整的端到端系统,还需要攻克许多挑战。但没有挑战,又何以谈生活呢?
敬请期待下一阶段!