前言

虽然多数情况下照片的exif (Exchangeable image file format,图像元数据格式) 信息中已经包含GPS坐标,对它们的定位十分简单。但我们所能接触到的照片很少会是原片(脱去了exif),通常都不含任何有价值的信息,甚至有时候exif数据可能是被特意篡改的,这使得判断拍摄地点变得异常困难。我们可能需要人工提取图中的特征,与现实的各个可能地点进行比对,如果需要比对的地点足够多,对照片进行定位几乎是不可能的。

这种情况下,我们可以借助一些成熟的图像特征匹配技术,来代替人工。使用机器可以快速得出相似度最高的可能地点,大大提高处理的效率。

为了更好地解释图像检测的过程,本文会涉及一些基础的计算机视觉和神经网络概念。

工作原理

pytorch 实现了 torch 库 (C语言编写的后端) 的python接口,用于机器学习。它支持NVIDIA的CUDA技术,可以实现方便的硬件加速。

我们使用pytorch的 torchvision 来做图像处理和识别,torchvision提供了多个数据集和模型架构。

图像识别

这是整个项目的重点,其性能直接决定了我们图像对比的准确性。

torchvision.models内置了多个模型用于图像检测相关用途,这里我们使用 ResNet

我们可以把图像数据读入ResNet,生成相应的样本,用于图像对比。

Pytorch的文档告诉我们,可以直接使用他们的预先训练模型,这样可以节省大量时间和精力,也能保证基本的图像识别性能。

pytorch可以通过传递pretrained=True参数来直接构建预训练模型。我们在这里封装了一个class,可以对resnet的多个版本进行方便调用。

下图展示了ResNet提取图像特征并分类的过程。我们图像对比的实现思路是,从ResNet提取图像的特征,然后求两个图像特征的相似度。

使用预训练的ResNet,需要对图像数据进行normalize(归一化)处理。pytorch文档的说明如下:

Histogram可以作为图像数据的描述,我们从ResNet输出的tensor (可以理解为特征向量),最终求得图像的histogram。

从图像读取到产生histogram的过程:

  1. 读取图像,进行归一化处理

  2. 使用torch.autograd()求导,计算出图像数据输入resnet之后的路径

  3. 得到resnet输出的tensor,也就是该图像的特征向量

  4. tensor转换为numpy数组,进行flatten,我们会得到一列数值

  5. 每个数值除以所有数值之和,分别得到概率,这时的d_hist就是最终需要的histogram

接下来的工作是

  1. 根据histogram计算输入图像与目标图像的偏离度

distance方法如下,它支持多种计算方法,比较常用的是求差和cosine。

我们这里使用d1类型的distance计算,也就是简单求差取绝对值。

街景图数据

由于目前公开提供街景图数据的地图厂商很少,权衡之后我们选择 百度的方案 ,花销更小,基本也可以满足演示需求。

如果对数据全面程度和质量有更高要求,可以选择 Google的街景图place photos数据库 ,但收费不菲。

兴趣点搜集

POI (Place of Interest) 是一个互联网地图的概念,任何具有意义的地点都可以成为兴趣点,例如商店,学校大门,或者特定建筑物。

我们的做法是在确定中心点之后,在它附近搜集所有兴趣点的街景图,这样可以进一步增大命中几率。

如图,我们使用百度地图的POI搜集API,在中心点附近搜集十个类型的POI(因为API限制),并把它们的POI代码返回。

这样,我们就去抓取这些POI的街景图,并存储作为待对比的样本。

效果测试

我们下载一张中关村软件园国际软件大厦的正面部分照片,无明显标识,作为待定位图片:

为了节省时间,我们选择旁边的华夏科技大厦作为查询的中心点,通过百度地图查询的POI中应该会包含国际软件大厦,然后,行政区域限定为北京:

下图是华夏科技大厦:

偏离度(distance,越小则越接近)几乎相同的国际软件大厦局部照片:

由于华夏科技大厦的建筑风格与国际软件大厦类似,然后百度地图没有国际软件大厦正面照片,所以这个华夏大厦的正面照片以一个勉强的偏离度成为了最佳结果。

在数据源足够好的情况下,我们应该可以看到0.2以内的偏离度。

改进方向

增加街景图数据

这应该是最直接的改善途径,存在更多图片数据意味着有更多机会发现相似的图片,也就可以得到更精确的结果。

分布式计算

性能是一个巨大的问题,在使用CPU时,我们需要花费一两分钟处理几十张图片(计算histogram),CUDA可以把这个过程大大缩短。

但实际使用中我们可能需要处理上百张甚至上千张图片,分布式计算可以把重负荷的任务下发给GPU集群,从而成倍地加快处理速度,可以让这个系统变得实用。

使用街景图数据训练ResNet

Pytorch提供的pretrained数据来自ImageNet,并没有对街景图识别做针对性优化。如果我们需要更好的效果,应该使用自己的数据来训练。

这也是一个重要的改进方向。目前使用ResNet的识别效果差强人意,但有些时候,它得出的正确地点图片与query图片的distance并不会排在top5,使得识别的准确性大大下降。

参考资料

相关文章