OSM(OpenStreetMap)是一个开放的,用户可编辑的世界地图。AOI(Area of Interst)为兴趣面,包含以个区域内的如名称,土地用途等各种信息,在实际应用中我们常常希望得到以AOI划分的要偶感影像。本文将介绍获取OSM的AOI,并进一步获取到AOI区域遥感影像的方法。本文将步骤大致分为获取AOI、获取影像、裁剪影像三步。
[out:csv(number,length)][maxsize:1000000000]; [[:Template:GeocodeArea:Sweden]]->.searchArea; way["highway"="path"]["foot"!~".*"]["bicycle"!~".*"]["segregated"!~".*"](area.searchArea); make stat number=count(ways),length=sum(length()); out;
defosm_request(lat1, lon1, lat2, lon2): flag = True while flag: try: try: # 查询 query = ("[out:json];\n" "(\n" "way[\"landuse\"=\"residential\"]({0},{1},{2},{3});\n" "node(w);\n" ");\n" "out;\n").format(lat1, lon1, lat2, lon2) osm_op_api = overpy.Overpass() result = osm_op_api.query(query) except ConnectionResetError as e: # 划分成更小的范围 print(e) result = overpy.Result() dim = 3# 划分成3*3 for i in range(dim): for j in range(dim): temp = osm_request(lat1 + (lat2 - lat1) / dim * i, lon1 + (lon2 - lon1) / dim * i, lat1 + (lat2 - lat1) / dim * (i + 1), lon1 + (lon2 - lon1) / dim * (i + 1)) result.expand(temp) flag = False except (Exception, overpy.exception.OverpassTooManyRequests) as e: # 休眠一段时间重新查询 print(e) time.sleep(60) return result
way = result.ways[0] # 获取Way的feature tag = way.tags # 获取Way的ID id = way.id # 得到的是像result格式一样的Nodes nodes = tags.get_nodes() # 得到的是组成Way的Nodes的ID列表 node_id = tags._node_ids # 获取Node的纬度和经度 lat, lon = nodes[0].lat, nodes[0].lon
下面以将AOI信息保留至CSV文件为例子。
defway2csv(way, key_list): line = "" # 只保留需要的信息 for k in way.tags.keys(): if k in key_list.keys() and way.tags[k] in key_list[k]: line += "%s, %s,%s" % (way.id, k, way.tags[k]) break # 找Node的坐标记录下来,可提前将Node存入字典nodes_list方便查找 for id in way._node_ids: if id in nodes_list: line += ",%s,%s" % (nodes_list[id][0], nodes_list[id][1]) return line
# AOI获取 wayset = result.ways fway = open("%s_aoi.csv" % name, "w+") for way in wayset: fway.write(way2csv(way, key_list) + "\n") fway.close()
# 新建一个正确大小的画布 outpic = pil.new('RGBA', (lenx * 256, leny * 256)) for i, data in enumerate(datas): # 获取到每一个瓦片的数据 picio = io.BytesIO(data) small_pic = pil.open(picio) # 将数据写入画布的正确位置 y, x = i // lenx, i % lenx outpic.paste(small_pic, (x * 256, y * 256))