为校园生成街景

给学校做一个街景是大一入学以来一直以来的一个愿望了。在大二的时候,我们已经为学校拍摄了数张航拍全景,本想打算以此为基础为学校做一个完整的全景覆盖的,可惜疫情之后学校就不再让学生在未经老师允许的情况下飞行无人机了。街景的实现方式也从无人机变成了土制街景单车(误)。

拍摄前准备

从这张拍摄中截取的街景图片中能够看到土制街景单车的基本配置。全景车的基础是一台自行车,并且在车辆的车把左半部分通过GoPro通用接口挂接了相机的自拍杆,右边用于放置记录地理信息和罗盘方位的手机或者其他GPS设备。

土制街景单车
土制街景单车

全景相机

这次拍摄使用的全景相机是Insta360 One X,两侧各有一个1200万像素的全景镜头,拼合起来的图片为6080*3040,大概1800万像素。成像质量一般,拉近来看估计还没有大部分手机的广角镜头好。

本次拍摄时,我们使用了一个自拍杆接在相机上,并把相机接进了车头上的转接件里。但这种方案一旦车动起来,自拍杆是没有办法保持垂直的(也许可以使用下图的这种方法,但看起来不是很好保持相机的水平和方向)。因此我们还需要用一只手稳住自拍杆,另一只手操控车把和刹车。(在此情况下,请做足个人保护措施,勿使用抓住自拍杆的手单手骑车,并时刻注意周边环境!

挂载全景相机的一个例子
挂载全景相机的一个例子

手机/GPS

Insta360 One X是没有内置GPS的(App里面的记录GPS选项只能记录第一张照片的GPS,约等于没用)。因此我们需要在车把右侧挂载手机用于记录GPS和图片的拍摄方位。这里推荐使用OSMTracker for Android来进行记录。在导出数据的时候,需要在Settings-Export compass heading里面勾选in extension 来把方向(指南针)数据导出到GPX文件里面。

拍摄

在约8km/h的骑车速度下,将相机设置成间隔拍摄,5秒拍摄一张即可,这样两张图之间大概会间隔10米左右。

后期处理

在手机记录完GPX数据之后,我们可以在应用里面选择以GPX格式导出即可。

修正GPX数据偏移

这应该属于One X的一个硬件Bug,相机的EXIF时间戳总是会比相机时钟慢上10秒左右。同时,长期不连接手机还会造成其他的时钟偏移问题。因此,我们需要首先寻找EXIF时间戳和GPS的时间差。由于没有其他的参考,这次拍摄中我们就只能使用卫星图和拍摄出来的周围景色对照来计算时间偏差了。

万幸的是,南科大的校园里有大量的黄色减速带。减速带大概长这样:

找不到本校的减速带照片了,图中是CUHK的减速带
找不到本校的减速带照片了,图中是CUHK的减速带

使用Geosetter将经过减速带时图片的EXIF时间戳和通过减速带时GPX的时间戳进行对比,我们就可以计算出相机时钟的漂移了。(这个软件还能显示图片EXIF中的方位和叠加GPX路径,在验证GPX路径的时候相当方便)

Geosetter的界面
Geosetter的界面

通过GPSBabel,我们就能快速偏移GPX轨迹的时间戳,对齐EXIF时间戳和GPX时间戳了:

gpsbabel -t -r -w -i gpx -f intput.gpx -x track,move=+12s -o gpx -F out.gpx

(在拍摄中,第一天的偏移是11s,第二天是51s)

修正指南针数据标签

由于在将geotag数据标记到图像EXIF数据的过程中,exiftool读取不到原始GPX数据的坐标。我们需要将GPX文件中方向的tag进行修正。在GPX文件中,将所有的<compass>标签改为<course>即可。

通过delta GPS坐标修正图片方向

万一你的手机没能记录下正确的方向数据,我们也可以用求GPS轨迹切线斜率的方法得出大致的方向。使用下方的python代码即可:

import numpy as np
import pandas as pd
from geographiclib.geodesic import Geodesic
import xml.etree.ElementTree as ET



gpx_tree = ET.parse('input.gpx')
gpx_root = gpx_tree.getroot()

# 2520是gpx的路径点数量
for i in (range(0,2520)):
    gpx_root[1][1][i][2][1].text = str((float(gpx_root[1][1][i][2][1].text) + 180)%360)
    # 如果相机的显示器这一面与行车方向相反,则需要把路径调转180度

gpx_tree.write('modified.gpx')

Geotag

使用exiftool完成即可,需要注意GPX文件/图片的EXIF有可能是不带时区的,因此同步位置信息的时候还需要添加一个时区偏移(8小时即28800秒)。(其他的同步选项可以参考这个网页)

exiftool -geotag output.gpx -geosync=+28800 DIR

模糊车牌和人脸

根据mapillary论坛上网友的建议,本次我们选择使用understand-ai/anonymizer来模糊街景中的车牌和人脸。将repo clone下来之后,新建一个python3.6的anaconda环境,按照requirements.txt里面的包安装即可。程序第一次运行的时候需要从Google Drive下载模型,此处可能需要添加代理。

PYTHONPATH=$PYTHONPATH:.

python anonymizer/bin/anonymize.py --input input-folder --image-output output-folder --weights weights --face-threshold=0.1 --plate-threshold=0.1  --obfuscation-kernel 47,1,9

使用GTX1660Ti显卡时,模型的处理速度大约是2秒一张图。

处理进度图
处理进度图

同步EXIF

模糊完车牌和人脸之后的文件也被抹去了exif信息,这时还需要用输入图片同步EXIF数据到输出图片。

# copy EXIF as a block between same-named JPG files in different directories
exiftool -tagsfromfile SRCDIR/%f.%e -exif -ext jpg DSTDIR

生成全景网页

使用pano2VR生成即可。这个软件提供了制作街景中比较关键的设置图像联系,添加控制按钮等功能。

在软件自动生成完全景之后,可能需要自己处理一下节点之间不正确的连接关系和GPS位置错误的图像。

pano2vr的界面
pano2vr的界面

最后导出即可。

Demo