1
5

More than 3 years have passed since last update.

現在地から写真の撮影場所までのルートを表示する

Posted at

概要

写真のExif情報から位置情報を取得できることを知ったので
その応用ということで、現在地から取得した位置情報へのルートをDirections APIで取得してみようと思いました。
ついでに、Exif情報から逆ジオコーディングを行って地理情報を同時に表示させます。
素人にも扱えるなんて、Googleさんは素晴らしいですなぁ。。

Exif情報についてはwikiを参照してください。
以下、引用文。

カメラの機種や撮影時の条件情報を画像に埋め込んでいて、ビューワやフォトレタッチソフトなどで参照、応用することができる。

逆ジオコーディングについては以下を参照してください。
以下、引用文。

経度緯度から住所を取得する方法を「リバースジオコーディング」や「逆ジオコーディング」と言います。

完成系

ただローカルで動かす程度なので、フロントには全くこだわっていません。
簡単に説明しますと、以下の処理を組んでいます。

①ホームディレクトリ/から写真を/uploadにアップロード(POST)
②flaskのルーティングメソッドで写真のオブジェクトを取得
③写真のExif情報からgps情報(緯度・経度)を取得
④取得した緯度・経度から逆ジオコーディングによって地理情報を取得
⑤gps情報・地理情報を地図表示ページに渡す
⑥地図表示ページでgooglemapを展開し、現在地と写真の撮影地とをルートマップとして表示する。またマップの上部に写真の地理情報を箇条書きで表示する。

スクショで表すとこうなります。(位置情報や地図情報は念のため隠しました。(;^ω^))
home.pngupload.png
A...現在地 B...目的地です。

工夫したこと・勉強になったこと

①地図の中心位置は、両者の中間地点にした!

google maps apiに渡すパラメータのうち、center(いわゆる地図の中心位置となるgps情報)を渡す必要があるが、単に現在地と写真の位置を足して2で割った値を中心にすると綺麗に地図が表示されるようになった。

Route.js
function successRoute(position) {

    var latitude  = position.coords.latitude;//緯度
    var longitude = position.coords.longitude;//経度
    // 位置情報(現在地)
    var latlng_local = new google.maps.LatLng( latitude , longitude ) ;
    // 位置情報(写真)
    var latlng_photo = new google.maps.LatLng( photo_data[0] , photo_data[1] ) ;

    // mapの中心
    center_lat = (latitude + photo_data[0]) / 2
    center_lng = (longitude + photo_data[1]) / 2
    const center = {lat: center_lat, lng: center_lng };
    const options = {zoom: 7, scaleControl: true, center: center};



②Pyモジュールからjavascriptに変数を渡す工夫

こちらの記事を参考にしました。
順序通り説明すると、以下の流れになります。

①app.pyモジュール側にて、渡したい変数(今回はgps情報と地理情報)をリストに格納する。(地理情報はString型で受け取るのでリストに入れ直す必要がある。)

②最終的に変数を渡したいRoute.jsを司っている、map.htmlファイルにリスト化した変数を渡す。

③map.htmlの<script>タグ内で、jinja2受け取った変数をjsonにエンコードしたものとして再定義する。

④再定義した<script>タグの下に<script>タグを用意し、Route.jsをソースとして定義する。

この流れを組むと、無事js内で変数が使えるようになりました。
以下に、コードの一部を掲載しておきます。

app.py
# コードは一部を抜粋
input_data = []
photo_info = []
@app.route('/upload', methods=['POST'])
def upload():
    # Exifからgps情報を取得する(image_pathはアップロードした写真のパス)
    # exif_gps.pyのget_gps関数による処理で緯度経度を取得
    photo_lat, photo_lng = exif_gps.get_gps(image_path)
    # gps情報をリストに格納
    input_data = [photo_lat, photo_lng]
    # 逆ジオコーディング処理で地理情報を取得する
    photo_info_tmp = exif_gps.revgeo(photo_lat, photo_lng)
    # photo_info_tmpはカンマを含む文字列(String)なので
    # photo_info_tmpに含まれた文字数分インクリメントしながら
    # カンマ以外の文字列をリストに格納する(ココ重要)
    num = 0
    note = ""
    for i in photo_info_tmp:
        if i != ',':
            note += i
            continue
        else:
            photo_info.insert(num, note)
            num += 1
            note = ""
    # map.htmlに変数を渡す
    return render_template('map.html', data=input_data, info=photo_info)
map.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>位置情報取得サンプル</title>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=XXX:bow:X"></script>
<script type="text/javascript">
// 変数を渡す
var photo_data= {{ data | tojson }}
var map;
</script>
<script src="{{ url_for('static', filename='js/Route.js') }}"></script>
</head>

参考にさせて頂いたサイト:bow:

◆google maps 導入手順
http://toa.in.net/googlemap/

◆参考書籍
https://www.socym.co.jp/book/1251

◆Exifから緯度経度の取得に対するエラー
https://stackoverflow.com/questions/64405326/django-exif-data-ifdrational-object-is-not-subscriptable

◆Directions Service 導入手順
http://www.googleappsscript.info/2018-03-21/map_route_guidance.html

◆Exifの取得
https://geocoder.readthedocs.io/providers/OpenStreetMap.html

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5