移动设备上的快速图像识别实验
当我们开发应用程序 BooksPlus 以改变读者的体验时,我们的机器视觉和图像识别试验之旅加速了。BooksPlus使用图像识别使打印的页面栩栩如生。用户可以通过使用 BooksPlus 应用程序扫描书中的图像来沉浸在丰富的交互式内容中。
例如,您可以扫描一篇关于诗人的文章并立即收听诗人的音频。同样,您可以扫描历史艺术品的图像并观看纪录片剪辑。
当我们开始开发时,我们使用了市售的 SDK,当我们尝试在本地识别图像时效果非常好。尽管如此,当我们的图像库超过几百张图像时,这些都会失败。一些服务执行基于云的识别,但它们的定价结构不符合我们的需求。
因此,我们决定尝试开发我们自己的图像识别解决方案。
我们实验的目标是什么?
我们专注于构建一个可以扩展到我们需要识别的数千张图像的解决方案。我们的目标是在实现高性能的同时灵活地进行设备上和云端图像匹配。
当我们扩展 BooksPlus 应用程序时,目标是建立具有成本效益的结果。我们确保我们自己的努力与 SDK 一样准确(在误报和误报匹配方面)。我们的解决方案需要与原生 iOS 和 Android 项目集成。
选择图像识别工具包
我们旅程的第一步是将图像识别工具包归零。我们基于以下因素决定使用OpenCV :
- 丰富的图像相关算法集合:OpenCV 集合了超过2500 种优化算法,得到了学术界和工业界的诸多贡献,是最重要的开源机器视觉库。
- 人气:OpenCV估计下载量超过1800万,拥有4.7万用户社区,技术支持丰富。
- BSD 许可产品:由于 OpenCV 是 BSD 许可产品,我们可以根据需要轻松修改和重新分发它。由于我们想为这项技术贴上白标,OpenCV 将使我们受益。
- C 接口:OpenCV 有 C 接口和支持,这对我们来说非常重要,因为原生 iOS 和 Android 都支持 C;这将允许我们为两个平台拥有一个代码库。
我们旅程中的挑战
在为我们的用例开发有效的解决方案时,我们面临着许多挑战。但首先,让我们先了解图像识别的工作原理。
什么是图像识别中的特征检测和匹配?
特征检测和匹配是每个计算机视觉应用程序的重要组成部分。它检测物体、检索图像、机器人导航等。
考虑以略微不同的角度单击单个对象的两个图像。你如何让你的手机识别两张图片包含相同的对象?特征检测和匹配在这里发挥作用。
特征是表示图像是否包含特定模式的一条信息。点和边可以用作特征。上图显示了图像上的特征点。必须以一种在光照、平移、缩放和平面内旋转变化下保持不变的方式选择特征点。使用不变特征点对于成功识别不同位置下的相似图像至关重要。
第一个挑战:性能缓慢
当我们第一次开始使用 OpenCV 进行图像识别实验时,我们使用了推荐的 ORB 特征描述符和 FLANN 特征匹配 2 个最近邻。这给了我们准确的结果,但速度非常慢。
设备上的识别对几百张图像效果很好;商业 SDK 在 150 张图片后会崩溃,但我们能够将其增加到 350 张左右。但是,这对于大型应用程序来说是不够的。
要了解这种机制的速度,请考虑一个包含 300 张图像的数据库。匹配图像最多需要 2 秒。以这种速度,包含数千张图像的数据库将需要几分钟来匹配一张图像。为了最好的用户体验,匹配必须是实时的,一眨眼的功夫。
需要最小化在管道的不同点进行的匹配数量以提高性能。因此,我们有两个选择:
- 减少附近的邻居数量,但我们只有 2 个邻居:尽可能少的邻居。
- 减少我们在每张图像中检测到的特征数量,但减少数量会影响准确性。
我们决定每张图像使用 200 个特征,但时间消耗仍然不能令人满意。
第二个挑战:低准确度
另一个存在的挑战是在匹配包含文本的书籍中的图像时准确性降低。这些书有时会在照片周围有文字,这会给文字添加许多高度聚集的特征点。这增加了噪音并降低了准确性。
一般来说,这本书的印刷造成的干扰比其他任何事情都多:页面上的文本创建了许多无用的特征,高度聚集在字母的锐利边缘上,导致 ORB 算法忽略了基本的图像特征。
第三个挑战:原生 SDK
在解决了性能和精度的挑战之后,最终的挑战是将解决方案封装在一个支持多线程并兼容 Android 和 iOS 移动设备的库中。
我们的实验导致了解决方案:
实验 1:解决性能问题
第一个实验的目的是提高性能。我们的工程师想出了一个提高性能的解决方案。我们的系统可能会出现任何具有数十亿种可能性的随机图像,我们必须确定该图像是否与我们的数据库匹配。因此,我们没有进行直接匹配,而是设计了一种两部分的方法:简单匹配和深度匹配。
第 1 部分:简单匹配:
首先,系统将消除明显的不匹配。这些是很容易被识别为不匹配的图像。它们可以是我们数据库中数千甚至数万张图像中的任何一张。这是通过非常粗略的级别扫描完成的,该扫描仅考虑 20 个特征,通过使用设备上的数据库来确定正在扫描的图像是否属于我们感兴趣的集合。
第 2 部分:深度匹配
在第 1 部分之后,我们只剩下很少有来自大型数据集(有趣的集合)的具有相似特征的图像。我们的第二个匹配步骤是在这几幅图像上进行的。仅对这些有趣的图像进行了深度匹配。为了找到匹配的图像,这里匹配了所有 200 个特征。因此,我们减少了在每张图像上执行的特征匹配循环的数量。
每个特征都与训练图像的每个特征相匹配。这将匹配循环从 40,000 (200×200) 降低到 400 (20×20)。我们将获得一个最佳匹配图像列表,以进一步比较实际的 200 个特征。
我们对结果非常满意。以前需要 2 秒才能匹配图像的 300 张图像的数据集现在只需要 200 毫秒。这种改进的机制比原来的机制快 10 倍,延迟时人眼几乎察觉不到。
实验 2:解决规模问题
为了扩大系统规模,第 1 部分匹配在设备上完成,第 2 部分可以在云端完成——这样,只有潜在匹配的图像才会发送到云端。我们会将 20 个特征指纹匹配信息连同检测到的其他图像特征一起发送到云端。借助包含有趣图像的大型数据库,云可以扩展。
这种方法允许我们在设备上拥有一个大型数据库(功能较少),以消除明显的不匹配。内存需求减少了,我们消除了由于系统资源限制导致的崩溃,这是商业 SDK 的一个问题。由于真正的匹配是在云中完成的,我们能够通过不使用云 CPU 循环来降低云计算成本来进行扩展,从而避免明显的不匹配。
实验 3:提高准确性
现在我们有了更好的性能结果,匹配过程的实际精度需要提高。如前所述,在现实世界中扫描图片时,噪声量非常大。
我们的第一种方法是使用 CANNY 边缘检测算法找到图像的正方形或矩形边缘,并裁剪掉其余数据,但结果并不可靠。我们观察到两个仍然很重要的问题。首先是图像有时会包含作为整个图像矩形一部分的标题。第二个问题是图像有时会在美学上以不同的形状放置,如圆形或椭圆形。我们需要想出一个简单的解决方案。
最后,我们分析了 16 种灰度的图像,并试图找到仅偏向 2 到 3 种灰度的区域。这种方法准确地找到了图像外部区域的文本区域。找到这些部分后,模糊它们会使它们在干扰识别机制时处于休眠状态。
实验 4:为移动设备实现原生 SDK
我们迅速提高了特征检测和匹配系统识别图像的准确性和效率。最后一步是实现一个可以在 iOS 和 Android 设备上运行的 SDK,就像我们在原生 SDK 中实现它们一样。对我们来说,Android 和 iOS都支持在其原生 SDK 中使用 C 库。因此,使用 C 语言编写了一个图像识别库,并使用相同的代码库生成了两个 SDK。
每个移动设备都有不同的可用资源。高端移动设备具有多个内核以同时执行多个任务。我们创建了一个具有可配置线程数的多线程库。该库将根据移动设备的最佳数量在运行时自动配置线程数。
结论
总而言之,我们通过提高机器视觉的准确性和效率开发了一个大规模的图像识别应用程序(用于包括增强现实在内的多个领域):特征检测和匹配。现有的解决方案速度很慢,我们的用例产生的噪音大大降低了准确性。我们希望在眨眼之间获得准确的匹配结果。
因此,我们进行了一些测试以提高该机制的性能和准确性。这将特征匹配循环的数量减少了 90%,从而使匹配速度提高了 10 倍。一旦我们获得了我们想要的性能,我们就需要通过减少图像中文本周围的噪音来提高准确性。在分析 16 种不同灰度的图像后,我们能够通过模糊文本来实现这一点。最后,所有的东西都被编译成可以在 iOS 和 Android 上使用的 C 语言库。