PyOsmium入門


PyOsmiumとは

PyOsmiumはosmiumというライブラリをpythonで使用できるようにするモジュールです。
Osmiumは、ノード、ウェイ、リレーション、チェンジセットなど、幅広くサポートしています。変更ファイルや完全な履歴ファイルを含む、XML、OSM および PBF フォーマットの読み書きが可能です。

インストール

pip install osmium

osmの主なデータタイプ

Node

緯度と経度を指定することによって地点を表します。信号やベンチなどの物体の地点を表すのによく用いられます。

<node id="190137966" visible="true" version="11" changeset="60251867" timestamp="2018-06-28T14:59:36Z" user="Miyajimarumo" uid="6336964" lat="35.7208610" lon="139.4069943">
  <tag k="highway" v="traffic_signals"/>
  <tag k="name" v="砂川五差路"/>
</node>

Way

ノードの集合であり、道や川を表す際に用います.また,wayで閉じた図形を描くことにより,建物などの,ポリゴンも表すことができます。

<way id="81791723" visible="true" version="4" changeset="26246450" timestamp="2014-10-22T01:06:11Z" user="txma25918" uid="955553">
  <nd ref="1339636471"/>
  <nd ref="952845077"/>
  <nd ref="3142965192"/>
  <nd ref="952845075"/>
  <tag k="highway" v="unclassified"/>
 </way>

Relation

ノード、ウェイなどのメンバーを持ち、内側にあるのか、外側にあるのかなどの関係性をあらわします。Relationの意味はtagによって定義されます。(Route,Multipolygonなど)

<relation id="9734761" visible="true" version="2" changeset="73377379" timestamp="2019-08-15T11:22:37Z" user="8dirfriend" uid="3315483">
  <member type="way" ref="700632231" role="outer"/>
  <member type="way" ref="700632232" role="inner"/>
  <tag k="amenity" v="public_bath"/>
  <tag k="building" v="yes"/>
  <tag k="name" v="昭島温泉;湯楽の里"/>
  <tag k="type" v="multipolygon"/>
</relation>

Tag

タグは「キー」と「値」という2つの項目から構成されています.タグは地図の要素(ノード、ウェイ、リレーション)や変更セットについて、特定の地物や特徴を記述します。どちらも自由な書式の文字列フィールドであるが、数値やその他の構造的な項目を表すこともあります。

<tag k="highway" v="unclassified"/>

使用するファイルのダウンロード

geofabrikというosmのデータを扱いやすく加工してくれているサイトのファイルを使用します。
https://download.geofabrik.de/asia/japan.html

この中から使用したい地域のデータをダウンロードします。

データの抽出

上記のデータをpyosmiumを用いて抽出してみます。

import osmium
class CafeHandler(osmium.SimpleHandler):
    def __init__(self):
        super(CafeHandler, self).__init__()
        self.cafes = []

    def node(self, o):
       if o.tags.get('amenity') == 'cafe' and 'name' in o.tags: #o.tags.get(key)==value
            self.cafes.append(o.tags['name'])


h = CafeHandler()
h.apply_file('./shikoku-latest.osm.pbf')

print(sorted(h.cafes))
print(len(h.cafes))

実行結果

[,,,'サンマルクカフェ', 'サンマルクカフェ 丸亀VASALA店', 'サンマルクカフェ 愛媛県立中央病院店', 'シモノロ食堂', 'シモノロ食堂', 'シャラの樹Ⅱ', 'ジャンキーノンキー', 'スターバックス', 'スターバックスカフェ', 'スターバックスコーヒー 松山中央店', 'スターバックスコーヒー 高松天満屋店', 'スプーン', 'ドリマの上', 'ドーム', 'ヒース', 'ピアノカフェルフラン', 'ピエロ', 'ピノキオ', 'ファンキータイム', 'ファンキータイム', 'フレンド', 'プチ・マドンナ', 'プランタン', 'ミスタードーナツ', 'ミント', 'メフィストフェレス', 'モンパリ', 'モンブラン', 'リーサ', '三日月とカフェ', '井戸端処ぼっこ', '六実庵', '友浦サイト', '古阿羅', '喫茶MOCA珈琲店', '喫茶スマイル',,,]
157

上記の例ではosmに記載されている四国のカフェの名前を抽出し、その個数をカウントしました。

import osmium
class RailHandler(osmium.SimpleHandler):
    def __init__(self):
        super(RailHandler, self).__init__()
        self.rails = []

    def way(self, o):
       if o.tags.get('railway') == 'rail' and 'name' in o.tags: #o.tags.get(key)==value
            self.rails.append(o.tags['name'])


h = RailHandler()
h.apply_file('./shikoku-latest.osm.pbf')

print(set(h.rails))

実行結果

{'郡中線', 'JR土讃線 伊予川橋梁', 'JR土讃線;穂岐山トンネル', 'JR本四備讃線', '土佐くろしお鉄道宿毛線', 'JR土讃線', 'JR鳴門線', 'JR内子線;JR予讃線', '中尾トンネル', 'JR土讃線;大杉トンネル', '高浜線', '横河原線', 'JR徳島線', 'JR土讃線 第一吉野川橋梁', 'JR高徳線', '伊予鉄道高浜線', 'JR予讃線', '高松琴平電気鉄道長尾線', '打除鉄橋', 'línea JR Kotoku', '土佐くろしお鉄道阿佐線', '阿佐海岸鉄道阿佐東線', '大王製紙専用線', 'JR予土線', 'JR内子線', '琴平線', '高松琴平電気鉄道志度線', '吉野川橋梁', '土佐くろしお鉄道中村線', '本四備讃線', 'JR牟岐線', '鳥越トンネル', '鉱山観光鉄道', '高松琴平電気鉄道琴平線', '予讃線'}

これらのようにtagのkeyとvalueを指定することによって、望んだ情報を抽出することができます。

最後に

pyosmiumはこれらの他にもwayの長さを計算したり様々なことができます。興味の湧いた方は是非使ってみてください。

以上となります。
最後までご覧いただきありがとうございました。

参考文献

https://osmcode.org/libosmium/
https://lonvia.github.io/geopython17-pyosmium/#1