谷歌发布地图「时光机」:100年前,你家街道长啥样?-1
10年前,乃至100年前,你长大的那条街道长什么样?
现在,除了用AI修复老影像资料,谷歌还发布了新的「时光旅行」方案。
就像这样,用3D视角,一览1890年到1970年曼哈顿切尔西区的建筑变化。
是不是有点历史更迭内味儿了?
这样一台「时光机器」的引擎,是谷歌推出的基于浏览器的工具集rǝ(音return),主要由3部分组成:
一个众包平台。用户可以上传城市历史地图,将其与现实世界的坐标进行匹配,完成地理修正,并将其矢量化。
一个时空地图服务器。能显示城市地图是如何随时间变化的。
一个3D体验平台。运行在rǝ地图服务器之上,利用深度学习,根据有限的历史图片和地图数据重建3D建筑,创造3D体验。
以众包方式打造
重现城市的过去,最大的难点就在于数据:可用的图像很少,从图像中获取的元数据比之现代地图自然也少得多。
为了应对这一挑战,谷歌的工程师们用上了基于Google Cloud和Kubernnetes运行的开源工具rǝ。
其作用在于,采用众包的方式,让用户们共同打造一个具有时间维度的地图服务器。
具体而言,用户可以通过浏览器上传各个年代纸质版地图的扫描件,对其进行地理校正,使历史地图与现实世界的坐标相匹配。
然后,通过追踪地理特征,比如标志性建筑、道路等,将历史地图转换成OSM矢量格式。
这些矢量地图经过图块服务器(tile server)的渲染之后,就会变成通常在谷歌地图上看到的,可以放大和平移的滑块地图(slippy map)。
重建3D模型
接下来,就是利用这些图像和地图数据,重建曾经在历史上出现过的建筑们的3D结构了。
这里的难点在于,大多数情况下,一个建筑的历史图像很可能只有一张。为此,谷歌工程师们开发了一套由粗到细的识别重建算法。
如图中所示,首先,根据众包注释或自动检测算法识别地图标记和历史图像中的建筑立面,为其生成粗略的3D结构。
与此同时,算法会识别建筑立面上所有窗户、入口、楼梯这样的独立组件,并根据其类别分别重建精细的3D结构。
两者相结合,就得到了最终的3D网格。这一结果会被存储在3D资源库中,为下一步渲染做好准备。
该算法涉及的SOTA深度学习模型包括:
用窗户、入口、楼梯这样的立面组件注释训练的RCNN,用于定位历史图像中的边框级实例。
语义分割模型DeepLab,提供每个语义类的像素级标签。
专门设计的神经网络,用以确保一个立面上生成的窗户之间间距相等、形状一致。同时也保证不同语义类,比如楼梯和窗户之间的一致性,使这些组件被放置到合理的位置上。
还原全球城镇,还有《微软模拟飞行》
在此之前,微软也和AI初创公司Blackshark.ai合作,上线了全球最大仿真游戏《微软模拟飞行2020》,通过机器学习2D转3D的模式,还原了全球200万个城镇、15亿座建筑物和3.7万个机场。
游戏一上线,知名游戏测评媒体IGN就给它打出了满分10分。
并且,Blackshark还透露,这样的技术未来或将用于自动驾驶。
那么,谷歌这次推出的怀旧项目你又觉得可不可呢?
如果你感兴趣,也不妨加入其中,谷歌表示,历史数据集和源代码均将开源~
道翰天琼CiGril机器人API
道翰天琼CiGril认知智能机器人API用户需要按步骤获取基本信息:
- 在平台注册账号
- 登录平台,进入后台管理页面,创建应用,然后查看应用,查看应用相关信息。
- 在应用信息页面,找到appid,appkey秘钥等信息,然后写接口代码接入机器人应用。
开始接入
请求地址:http://www.weilaitec.com/cigirlrobot.cgr
请求方式:post
请求参数:
参数 |
类型 |
默认值 |
描述 |
userid |
String |
无 |
平台注册账号 |
appid |
String |
无 |
平台创建的应用id |
key |
String |
无 |
平台应用生成的秘钥 |
msg |
String |
"" |
用户端消息内容 |
接口连接示例:http://www.weilaitec.com/cigirlrobot.cgr?key=UTNJK34THXK010T566ZI39VES50BLRBE8R66H5R3FOAO84J3BV&msg=你好&ip=119.25.36.48&userid=jackli&appid=52454214552
注意事项:参数名称都要小写,五个参数不能遗漏,参数名称都要写对,且各个参数的值不能为空字符串。否则无法请求成功。userid,appid,key三个参数要到平台注册登录创建应用之后,然后查看应用详情就可以看到。userid就是平台注册账号。
示例代码JAVA:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class apitest {
/**
* Get请求,获得返回数据
* @param urlStr
* @return
*/
private static String opUrl(String urlStr)
{
URL url = null;
HttpURLConnection conn = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try
{
url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5 * 10000);
conn.setConnectTimeout(5 * 10000);
conn.setRequestMethod("POST");
if (conn.getResponseCode() == 200)
{
is = conn.getInputStream();
baos = new ByteArrayOutputStream();
int len = -1;
byte[] buf = new byte[128];
while ((len = is.read(buf)) != -1)
{
baos.write(buf, 0, len);
}
baos.flush();
String result = baos.toString();
return result;
} else
{
throw new Exception("服务器连接错误!");
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
try
{
if (is != null)
is.close();
} catch (IOException e)
{
e.printStackTrace();
}
try
{
if (baos != null)
baos.close();
} catch (IOException e)
{
e.printStackTrace();
}
conn.disconnect();
}
return "";
}
public static void main(String args []){
//msg参数就是传输过去的对话内容。
System.out.println(opUrl("http://www.weilaitec.com/cigirlrobot.cgr?key=UTNJK34THXK010T566ZI39VES50BLRBE8R66H5R3FOAO84J3BV&msg=你好&ip=119.25.36.48&userid=jackli&appid=52454214552"));
}
}