写点什么

用开源软件写的 57 行代码,PK 掉 8600 万的商业项目!

  • 2017-09-19
  • 本文字数:2798 字

    阅读完需:约 9 分钟

维多利亚警察局是澳大利亚维多利亚的主要执法机构。去年,发生在维多利亚的盗车数量达到了 1.6 万辆,价值 1700 万美元,因为发生了这些,我们的警察开始忙于测试各式各样的技术和解决方案,尝试去打击那些偷车贼。

为了防止那些欺诈性质的,即售卖被盗窃车辆,一家叫做 VicRoads ,提供了基于 web的服务,可以检查车辆的注册情况,该部门也投资了车辆牌照的扫描仪,一个固定的三脚架摄像头,用于扫描过往的车流,以自动识别被盗车辆。

请不要问我发生过什么,有那么一天下午,我突发奇想,我自己何不做一个车载的车牌扫描仪,功能就是如果车主的车被盗或未注册,车主将会自动得到通知。在理解了各个组件的工作情况之后,我试图将它们组合起来,验证一下是否可行。

在经过了一系列的Google 搜索之后,我发现维多利亚警察最近也在试用一个类似的设备,他们预计的推出成本在8600 万美元左右。一位精打细算的评论员指出:“这笔8600 万美元,是为220 辆汽车装备此设备,相当于每台设备花费390,909 美元。”

相信我可以做的比这个更好!

成功的标准

在开始做这个设备之前,我列举了如下的一些关于产品设计的几个关键需求。

图像必须在本地处理

将直播的视频流上传到中央服务器看起来是解决此问题的最差的选择。除了数据流量大,需要花费的宽带费用很高之外,网络的延迟将无法保证最后的结果。

虽然说处于数据中心的机器学习算法会越来越准确,我以为能够在本地处理就足够了。

能够处理低质量的图片

我既没有树莓派的相机,也没有USB 的摄像头,我拥有的仅仅是普通的行车记录仪,它可以随车即时使用,是样品数据的理想来源。另外还有一个好处,即行车记录仪代表车载摄像头的整体质量,具有普遍性。

需使用开源软件构建

依赖于专有软件,也就意味着每次你有需求变更或增强功能,都得另外付费,——而且这个过程永无止境。毫无疑问,开源软件是默认选项。

解决方案

大体上来说,我的方案就是从行车记录仪中读取图片,将之传送到本地设备,本地的设备安装有开源的牌照识别系统,然后去查询注册服务,然后返回结果并进行显示。

返回到安装在执法车辆中设备的数据包括车辆的制造厂商和型号(以验证是否只是车牌被盗),注册状态,如果是被偷的车辆的话,就会发出通知。

聪明的读者是不是觉得挺简单的?是的,它确实也没有那么的复杂。举例来说,牌照的处理可以交由一个叫做 openalpr 的程序库,这其实就是所涉及到的识别牌照上的字符全部:

复制代码
openalpr.IdentifyLicense(imagePath, function (error, output) {
// handle result
});

轻微警告 公开访问 VicRoads 的 API 还不可用,因此此处涉及到的车辆牌照检查的 web 只是一个原型,或许有人看不惯——这只是一个概念验证,我并没有黑进任何服务器。

下面就是我写的用作概念验证的略显粗糙的代码:

复制代码
// Open form and submit enquire for `rego`
function getInfo(rego) {
horseman
.userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0')
.open(url)
.type('#registration-number-ctrl input[type=text]', rego)
.click('.btn-holder input')
.waitForSelector('.ctrl-holder.ctrl-readonly')
.html()
.then(function(body) {
console.log(processInfo(body, rego));
return horseman.close();
});
}
// Scrape the results for key info
function processInfo(html, rego) {
var $ = cheerio.load(html);
var vehicle = $('label.label').filter(function() {
return $(this).text().trim() === 'Vehicle:';
}).next().text().trim();
var stolen = $('label.label').filter(function() {
return $(this).text().trim() === 'Stolen status:';
}).next().text().trim();
var registration = $('label.label').filter(function() {
return $(this).text().trim() === 'Registration status & expiry date:';
}).next().text().trim();
return {
rego,
vehicle,
stolen,
registration
};
}

结果

我必须坦率的和大家说,结果着实令人吃惊。

我本以为开源的车辆牌照识别一定不怎么好用,另外,我甚至认为此程序未必正对澳大利亚的牌照进行过优化。

结果让我想到的意外,如它可以在较开阔的视野识别到车牌。

(图片说明:添加注释生效,尽管有强光发射、镜头失真,但是依然识别到了车牌。)

虽然解决方案有些瑕疵,即对于特殊字母的处理不够完美。

(图片说明:读牌照不够精准,将 M 读成了 H)

但是,还是可以接受的,大多数时候能够得出正确结果。

(图片说明:几帧之后,M 被正确识别,并具有更高的置信度)

正如你所看到的上面的两幅图,在多处理了几帧图像之后,可信度从 87% 上升到了 91%。

我开始对此方案有了足够的信心,对于双关语的处理,可以通过提高样本率可以提高准确性,然后按最高置信度来排序。或者,在接受验证注册号之前,设置一个阈值,如仅接受大于 90%的置信度的图片。

当然,这些都是可通过修改代码来让软件更加的完善,而且还可以使用本地的数据来训练车辆识别软件。

8600 万美元的问题

公平地说,我完全不知道不知道 8600 万美元都花在了哪里?我也不会说训练本地的机器学习开源软件,为了提高准确性,而毋需花费额外的金钱,或者是使用试验性质的 BlueNet 系统。

我还可以预估出来,这些预算还会包括替代旧的数据库和应用程序,从而能够支持每辆车,每秒中的被频繁的查询,以达到低延时的效果。

换句话说,每辆车花费 ~$391k 是很奢侈的,尤其是如果 BlueNet 不是特别准确,而且还没有大型的系统扩展,以及升级相关依赖的系统。

未来的应用

尽管这个系统,很容易被人认为是奥威尔式的“永远在线”的牌照网络监视,但是此项技术仍然有很多正面的意义。可以想象一下,这个系统可以扫描到前方的被盗窃的车辆,然后会发送信息给丢失爱车的车主或家人,信息包括车辆目前的位置和要去往的目的地,车主找回自己爱车的几率就会大很多。

特斯拉早已经实现了接收 OTA 更新功能的相机和传感器,—— 想象一下,这是多么强大的一组守护者。Uber 和 Lyft 的司机若配置了此设备,那么就可以覆盖更大范围的,让偷车贼无处可遁。

使用开源技术和现成的组件,似乎有可能提供一个提供更高回报率的解决方案 - 投资远低于 8600 万美元。

关于作者

Tait Brown,自称是一名 UX 设计师和开发者,会做一些和用户体验有关的事情,并乐意分享 tweet。

查看英文原文 How I replicated an $86 million project in 57 lines of code


感谢杜小芳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-09-19 19:006497
用户头像

发布了 33 篇内容, 共 11.6 次阅读, 收获喜欢 13 次。

关注

评论

发布
暂无评论
发现更多内容

你kin你擦!阿里终于肯把内部高并发编程高阶笔记开源出来了

Java架构之路

Java 程序员 架构 面试 编程语言

企业短信服务质量与用户体验如何监控?短信监测技术震撼来袭

博睿数据

短信 数据监测

第一周作业

Esther

胜天半子!阿里内部力荐SpringBoot全栈笔记全网首发,源码实战齐飞

Java架构之路

Java 程序员 架构 面试 编程语言

实现数字经济和实体经济深度融合

CECBC

区块链

阿里云 RTC QoS 屏幕共享弱网优化之若干编码器相关优化

阿里云视频云

音视频 WebRTC 网络 RTC 视频会议

阿里开源SpringSecurity:用户+案例+认证+框架

996小迁

Java 程序员 架构 面试 springsecurity

百度首届智能小程序高校大赛圆满结束:关注学生心理健康小程序获全国一等奖

DT极客

【盘点2020】机房网络性能哪家强?年度冠军揭晓

博睿数据

机房 评测

程序员生产环境-软件篇

ITCamel

程序员 效率工具 工作效率

LeetCode题解:105. 从前序与中序遍历序列构造二叉树,递归+哈希表,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

跨界融合,区块链推动实体经济提档升级

CECBC

人工智能 云计算 大数据

数字货币应用从C端走向B端 实践中这些难题仍需关注

CECBC

数字货币

观看辽篮比赛,思考团队管理——关于团队的灵魂拷问,你中了几个?

伯薇

团队管理 团队建设 团队 赋能 激励

技术分享 | 漫谈音视频中的拥塞控制

拍乐云Pano

关于JDK15的简单理解

Java架构师迁哥

客户服务高触达,零代码从短信/邮件跳转小程序客服

环信

永续合约APP系统软件开发

系统开发

一文读懂 Serverless,将配置化思想复用到平台系统中

Serverless Devs

Serverless 云原生 PaaS

EXCEL数据太“脏”无从下手?何须用python,ETL一分钟搞定

智分析

Excel ETL

万字带你深入阿里开源的Canal工作原理

大数据老哥

大数据 canal

​Kubernetes资源清单篇:如何创建资源?​

xcbeyond

Kubernetes 28天写作 Kubernetes从入门到精通

Android面试(二)

我就感觉到快

架构师训练营第三周作业 - 学习总结

阿德儿

边缘安全 | 正确使用CDN 让你更好规避安全风险

阿里云Edge Plus

安全 CDN

Soul网关源码阅读(八)路由匹配初探

Java 源码阅读 网关

大数据知识专栏 -MapReduce 自定义排序技术

小马哥

大数据 hadoop mapreduce 七日更

Redis 学习笔记 08:数据结构与对象小结

架构精进之路

redis 七日更 28天写作

蝉联 Apache 最活跃项目,Flink 社区是如何保持高速发展的?

Apache Flink

flink

为什么你家的 K8s 应用平台不好用?

孙健波

Kubernetes PaaS KubeVela

AES128解密只能解一半的问题

李日盛

AES 问题定位

用开源软件写的57行代码,PK掉8600万的商业项目!_语言 & 开发_李建盛_InfoQ精选文章