Microsoft Hackathon 2021

自动识别并举报交通违章

Posted by Di Chen on October 15, 2021

TOC generated by https://magnetikonline.github.io/markdown-toc-generate/

Hackathon 与我

我第一次参加 Hackathon 是在密西根大学的时候,当时 Hackathon 是 Barracuda 公司赞助的 AI 对决游戏。由 Barracuda 公司部署一台游戏服务器,调用每个参与者的 AI 进行对决,AI 负责对一个对称棋盘游戏进行决策,每次对决都会影响每个 AI 的名次。

那时候我对 Hackathon 的理解就停留在通宵写代码,快速地反馈,很好玩。后来才知道不是所有 Hackathon 都是游戏 AI 的形式,但游戏 AI 的对决 Hackathon 还是我参与过最好玩的。以至于我毕业了之后,也想要远程参与,因为看到自己写的 AI 把其他人一一打败的感觉真是太爽了。

微软 Hackathon

两个月前大白问我是不是想要参加微软 Hackathon 的时候,我其实是拒绝的,因为觉得 3 天的时间实在太短了,做不出什么有用的东西。但是一个偶然的机会,我成为了上海 Mini Garage 的维护者,知道公司可以给 Hackathon 的项目提供硬件支持。我就想到了我一直想做的一件事,自动举报交通违章。

路怒与我

在我开车上班的路上,会需要经过一个高架匝道,这个匝道往往需要在高架上排队10分钟以上才能进去。但是常常有人从空的车道超车之后,在匝道口变道加塞进来。刚开始的时候,我特别生气,别人要加塞我就不让,硬怼。但是每次我都会想,如果真的刮擦了,我也耽误了时间,还要修车,这是个双输的场景呀。难道就没有法律武器可以让我们用正当的方式解决这个问题么?

当我发现上海交警APP可以举报违章后,我就成了举报专业户,当其他车要加塞的时候,我不会再想着要跟紧前车不让加塞,而是想着留存证据,回头举报。其实这也让我开车的习惯更安全了,也让我的心情更平和。

不过举报的过程还是很繁琐,我需要:

  1. 回看行车记录仪,找到需要举报的片段。
  2. 把需要举报的片段下载到手机上。
  3. 剪辑视频,使得视频只包括需要举报的那20-30秒。
  4. 在上海交警APP上上传视频,选择违章地点,选择违章时间,输入号牌以及号牌颜色。

即使在特斯拉上可以一键保存当前的30秒视频,拔下储存卡拷贝的过程还是很繁琐。一次举报大概需要5-10分钟的时间。

优化思路

假设一个最理想的情况,我希望有这么一种行车记录仪:

  • 在开车的时候,它可以自动判断拍到的车辆的号牌、违章情况,同时把时间和地点上报到云端
  • 在停车之后,它可以把拍到的违章情况推送到手机上,如果用户同意举报,则以用户的身份把举报信息提交到交管部门。

显然,要实现这种理想情况的难度是很高的,主要在于:

  1. 车辆的号牌识别、以及图像处理是十分消耗能量的,对于 IOT 设备来说,除非有类似特斯拉这样专用的机器学习终端,否则处理速度是赶不上图像生成的速度的。
  2. 如果不在行车记录仪端进行数据处理,行车记录仪的高清全量视频 (每日几G)的传输也是十分消耗流量的,也不现实。

所以我们只能退而求其次,用一部分人工操作来替代人工智能。所谓的“人工智能主要靠人工”。

设备选择和 Hackathon 项目的由来

我的第一目标是寻找合适的行车记录仪,理想的行车记录仪可以通过4G访问,获取之前储存的视频、音频和GPS信息,这样行车记录仪就变成了一个数据库,可以接入任意的云端系统进行分析。我根据宣传语选择了盯盯拍,好贵呀,一个行车记录仪将近千元,也一直不舍得为了测试这个设备而花钱购买。

所以在知道微软支持购买设备后,就果断申请了。为了申请这个设备,也就设立了这个 Hackathon 项目。这也是这个项目的由来。

在拿到设备之后发现,盯盯拍的4G功能和我想象的不太一样,并不能直接通过4G访问行车记录仪上已储存的设备,只能被动地接受行车记录仪推送的一些警报视频。但好在它可以通过语音关键字 “我要拍照” 触发一段语音和视频的保存。这就简化了举报视频剪辑的步骤,我可以通过盯盯拍的 APP 下载已保存的视频。接下来可以设计一下实现的技术路径。

逆向探索并自动化

POC (Proof of Concept) 的研究过程需要搞清楚几件事情:

  1. 如何可以自动地获取到行车记录仪上通过语音关键字保存的视频信息。
  2. 如何获取到举报时的地点信息
  3. 如何获取到车牌信息
  4. 如何获取到违章类型
  5. 如何提交到上海交警
获取行车记录仪视频

我原本希望盯盯拍的行车记录仪可以通过4G远程访问以前储存的视频,结果发现4G只能访问实时的视频,并不能把访问历史视频,所以盯盯拍只能通过 wifi 下载视频。盯盯拍的本身有安卓和 iOS 的 App,连接了盯盯拍的 Wifi 之后,App 中有选择下载视频的选项,所以我们通过模拟 App 的操作就可以下载视频了。

行车记录仪这类的 IOT 设备为了研发方便,一般也使用 HTTP 协议,而且由于不会暴露在公网,往往也不会使用 TLS 加密。所以通过 HTTP 的 MITM 攻击抓包,就能找到下载行车记录仪视频的接口了。

要对行车记录仪进行 MITM 抓包,我先使用 iphone 连接了行车记录仪的 Wi-Fi,然后将 mac 也连接上行车记录仪的 Wi-Fi,在 mac 上打开 burp 监听,最后设置 iphone 上对应 wifi 的代理地址和端口为 mac 的 ip 和 burp 的监听端口。这个方案对其他的应用抓包一直都可以的,但是对于盯盯拍的应用却遇到了问题,盯盯拍的App请求没有出现在 burp 的 http 列表里。我怀疑是 iphone 对于 wifi 上设置代理有要求,如果 wifi 不能连接到互联网,则代理不生效。

后来额外尝试了一下,用安卓机上运行盯盯拍的 app 抓包就没有上述的问题,应该是安卓和 iOS 在 wifi 代理的实现细节上有一些区别吧。抓包后,盯盯拍上视频下载也就水到渠成了。

获取行车记录仪上的 GPS 历史记录

在抓包盯盯拍的过程中发现,http 请求中有一个请求是获取 GPS 文件列表的。这个文件列表的文件扩展名是 git 和 gpx。把文件下载下来后,把 git 文件和 gpx 文件上传到在线GPS信息可视化网站后发现,git 文件可以显示出我去过的 GPS 地点信息,但是 gpx 文件不能。所以先定位 git 二进制文件中包含了我们需要的地点信息。接下来就需要探索怎么解码 git 文件。

这里我选择了一个在线文件格式的分析工具,分析显示 git 是 tar 格式。尝试用 tar 解包,确认 git 确实是一个 tar 包。而 tar 包中是一批 gpx 文件的集合,而解压出来的 gpx 文件是文本文件,类似这样的格式

$GPRMC,081229.000,A,3113.54602,N,12130.79466,E,9.853,166.11,101021,,,A*4B
$GPGGA,081229.000,3113.54602,N,12130.79466,E,1,16,0.92,20.2,M,9.8,M,,*71
$GPRMC,081230.000,A,3113.54301,N,12130.79543,E,10.909,163.75,101021,,,A*72
$GPGGA,081230.000,3113.54301,N,12130.79543,E,1,16,0.92,20.2,M,9.8,M,,*79
$GPRMC,081231.000,A,3113.53965,N,12130.79648,E,12.227,167.43,101021,,,A*70

那么问题来了,这个文本怎么提取经纬度信息呢?用关键字$GPGGA 搜索后发现这是 NMEA 格式的头标志。有了具体的格式标准之后就容易解码了,找了一个网上已经实现好的 NMEA gps 信息转经纬度的 py 文件,就实现了 GPS 信息的提取。

获取违章车牌信息

违章车牌信息要求“违章” + “车牌”。我们可以先把车牌提取出来,然后再判断是哪个车牌发生的违章。车牌提取的部分,大白尝试了几个不同的路径。

一个是百度的车牌识别 API,这个 API 可以提取出车牌,但是不能提取出车牌在画面中的位置,也就意味着无法利用车牌来帮助违章类型的判断,这个对于后续的功能扩展会有一定局限性。

第二个是开源的项目,结合两个开源项目,一个进行车牌区域的识别,另外一个进行 OCR 提取文字。最终实现对于一张图像的车牌的提取。

对于视频中“违章”的判定是一个比较难的部分,因为违章需要多个规则,同时进行判断,例如对于车道线的识别,对于车辆位置和车辆灯语的识别。所以这目前来说并没有实现,我们只是简单地对车牌在视频中出现的帧数进行了统计并且排序,由用户进行最后的确认和选择。

获取违章类型

根据公开的新闻,10类常见的违章类型占了主要需要举报的违章类型。自动对违章类型的提取如果要实现,需要单独对每种违章类型实现判断逻辑。这次的 Hackathon 时间太短,这部分就没有做,而是用前端手动选择违章类型来替代。

如何提交到上海交警

将事件提交到上海交警的终端有两个选择,一个是 App,另一个是网页端提交接口。网页端更容易进行数据的抓包和分析,我优先选择了网页端进行抓包和分析,在实现了整个流程的提交代码后发现,“违法地址”这个字段的值需要从上海交警已保存的地址数据库中选择,而这个地址数据库不全,很多关键的交通要道在数据库中没有。所以最后弃用了网页端的提交接口。

上海交警的 App 提交接口分析首先需要对 App 进行抓包,抓包的方法和上述相同,这次抓包的流程相对顺利。但是对上海交警 App 的流量分析不太顺利,HTTP 请求的内容都是加密后的字符串。为了能模拟上海交警的请求,先从安卓的应用市场下载了安卓版的上海交警App安装包,然后用在线java反编译工具反编译了App。在反编译之后的源码包中,搜索关键字 “encyption” 并阅读代码发现,App 使用的是 DES3 的 desede/CBC/PKCS5Padding 算法进行编译,而默认的加密 key 和盐也可以在常量表中查找到。实际上每次用户登录前,会用默认的加密 key 和加密盐获取一次用户特定的 key 和盐,然后后续的请求都用新的 key 和盐来进行加解密。

在破解了请求的加解密之后,举报的提交也就水到渠成了,只需要只找到提交的 API,并且模拟它的请求参数即可。

剩下的一个难点在于视频的上传,通过源码包可以看到,上海交警的 App 中视频上传是使用的腾讯云的云点播服务,而腾讯云的上传客户端只有 iOS、安卓和 javascript 版,没有 python 版,也就不能在获取行车记录仪之后上传了。但是我们拆开腾讯云的服务器端上传的SDK源码文档可以发现:上海交警的客户端必定有接口从上海交警的服务器获取一个签名,拿到签名之后,再向腾讯云获取后续上传的密钥。所以找到上传时获取签名的接口就可以调用腾讯云后续的 COS 服务进行上传了。

在跑通上传流程之后,理论上整体的模拟提交流程也就完成了。

代码实现以及最终效果

前后端的实现和传统的网站差别不大,也是前后端分离,通过数据库持久化数据:

  • 前端是王涵娴实现的,一个登录界面,一个列表页和一个详情举报页。部署到 Azure Blob Storage 上,然后配置 static website hosting 提供服务。
  • 后端是用 Azure Function App 实现的几个简单的 python 接口。部署在 Azure Function App 上,毕竟这是一个小项目,可以节约部署成本。
  • 车牌识别因为依赖 torchopencv,相对比较重量级,所以打包成了 docker,部署在 Azure Container Instance 上,启动时拉取数据库中所有需要处理的举报信息,识别车牌后再更新数据库。为了平衡及时性以及成本,使用 Azure Automation 每小时启动一次 docker 跑批处理。
  • 数据储存为了方便,使用的是 Azure Storage 的 Table 服务,无 schema 限制,修改应用比较方便,也比较便宜。
  • 手机端的代码使用 Pythonista 运行一个 python 脚本,实现在手机上下载行车记录仪视频,并上传到腾讯云,然后把元信息调用 Azure Function App 的 http 接口储存下来。这里可能手机是最好的媒介,因为行车记录仪的 Wifi 是不能连网的,所以要同时下载行车记录仪的视频并且上传的话,就需要有一个 wifi 网卡,还需要一个 4G 网卡,否则只有 wifi 网卡的话,就只能下载不能上传了。而有双网卡的设备,最容易获得的就是手机了。
  • 持续集成使用的是 azure pipeline,毕竟是自家的 CI 系统,对 github 和 azure 的集成比较友好,可以快速集成代码到线上系统的编译和部署流程。

最终效果的 demo 可以看前面的视频:

项目下一步

这个项目从最后的效果来说我还是比较满意的,大大减少了我需要的时间。但是从对外推广的角度,还是不够令人满意,主要有几点:

  1. 手机端的使用要求高。Pythonista 是一个收费的 App,同时复制脚本的操作难度大,要推广给非程序员背景的人使用不现实。下一步可以把它做成一个手机 App,可能会好很多。当然,最好是行车记录仪的厂家可以直接支持上传视频和元信息到云端,技术上没什么难度,只要用户愿意出流量费就行了。但是和行车记录仪厂家沟通的成本会比较高,这条路子我不愿意去实行。
  2. 用户的认证不够完善,目前为了省事,没怎么做认证。下一步可以直接把上海交警App的账号密码作为认证的用户名密码加上。
  3. 行车记录仪的品牌型号依赖太强。目前下载视频的部分只在盯盯拍的mini5上实践过,而且关键词拍照录视频的功能,其他大部分品牌也是没有的。
  4. 目前只对接了上海交警的举报App,要是全国交警有一个统一的举报平台就好了。

结语

整个项目做下来还是很开心的,虽然一开始不太愿意报名,但是能最后把东西做出来,并且自己作为用户用得很舒服,让自己感觉到了学编程的初心。

在做完项目之后看了一下其他人的项目视频,发现有很多很精彩有意思的项目,果然给优秀的人资源和时间,他们就能给你很多惊喜。