Computer Vision

Python, Computer Vision, AI, Transhumanism 関連

画像から緯度経度を求める

最近、Google ライブビューのように、室内の画像から、位置情報がわかるような仕組みがある。

 

原理としては、あらかじめ撮影した画像を機械学習で、位置情報と紐づけておき、それを照らし合わせているのだろう。

 

位置情報(緯度経度)を得るのには、GPSがあれば良いのだが、GPSが届かない場所だと、いまだにそれに代わる決定的な方法がなかったりする。

 

そんなわけで、今回は、画像からの緯度経度の取り出しを想定した画像検索にチャレンジ。

 

で、いつもお世話になっている人工衛星の画像EO-Browserを使って、別日の画像から場所を特定してみた。

まずは、元画像を用意。2022/3/28撮影のデータ。

特に指定はないが、鮮明なものがよいだろう。

元画像に赤い印はつけてないが、今回の検出場所はここ。

なんの変哲ものない12px四方を選択。

 

それを別日の画像を対象に、12px四方を1pxずつづらしながら、似たような場所を探していく。

画像は 2022/4/22 ぱっと見ほとんど同じにみえるが1ヶ月近く異なる画像であり、データ的にはそれなりに違いのある画像となっている。

比較すればパッとわかるが、赤枠の画像のピースをこの462px四方の画像から

探すとなると、そこそこ難しいパズルゲームだと思う。

検出結果は上記のようになった。

1px違いで2重検出してしているが、若干ずれた画像でも検出できるということでもあり、それはそれで良い結果と言える。

 

x:199 y:200

緯度経度:35.62949442222222 139.65213896666666

 

x:200  y:200

緯度経度:35.62943174444444 139.65213896666666

 

計算と位置合わせが雑だったので、緯度経度は実際の場所とは100m程ずれたが、計算をしっかりすればよいだけなので、問題ないだろう。

緯度計算は元画像のピクセル座標を調べて出すのが正しいのだろうが、面倒なので開始点と終了点の座標を適当に確認しておいてそれをスケールに割り当てた。

 

今回一番肝心な部分は「似た場所を探す」という事だが、仕組みは12px画像を、diffして差分が小さかったところという手法を使った。

 

差分が0であれば単純だが、同じ場所を撮影した画像であっても、撮影ごとに明るさやゆがみは発生する。

つまり、差分は0でないものの、他の場所からの差分からするとかなり小さいということがこの画像検索が成立するための条件とも言える。

 

まあ説明するよりコードを見た方が早いかと思うので、コードも載せておく

 

diff-search.py

import cv2
import numpy as np

img1 = cv2.imread('t1.png',0) #グレースケールで取り出し
imga = img1[200:212, 200:212] #今回のターゲット画像 12px × 12px

img2 = cv2.imread('d2.png',0) #検索対照画像
img2 = img2[0:500, 0:500]  

img3 = cv2.imread('d2.png',1) #検出イメージの作成用なのでカラー
img3 = img3[0:500, 0:500]


#畳み込み
kernel = np.full((3, 3), 1/9)
ba1 = cv2.filter2D(imga, -1, kernel)


#横に1pxずつずらして450回それを縦方向にも450回実行
for y in range(0,450):
    for x in range(0,450):
        xe=x+12
        ye=y+12

        imgb=img2[y:ye, x:xe] #12pxの画像を取り出す
        kernel = np.full((3, 3), 1/9)
        bb1 = cv2.filter2D(imgb, -1, kernel)
        diff = cv2.absdiff(ba1,bb1)
        mn1=np.mean(diff)

        #差分をとって、meanをとりだし、その値が 6以下なものを今回は対象に
        if(mn1 < 6):
              print(x,y)
              #該当する場所に青枠を追加

              cv2.rectangle(img3, (x, y), (x+12, y+12), (255, 0, 0))

              #画像の座標を緯度経度に変換(適当)

              ulat=0.028205
              lat=35.6419673-(ulat/450*x)
              ulon=0.040992
              lon=139.6339203+(ulon/450*y)
              print(lat,lon)


#検出結果を画像として保存
cv2.imwrite("detect.png", img3)

今回のような差分による画像検索が成り立つためには、縮尺が一致していて、方角もかなり正確に一致している。天候も良好というのが条件になるが、画像一枚あれば特定できるというのはなかなかの成果かと思う。(自画自賛

 

meanにどんな意味があるのかとか、畳み込み処理はなにが美味しいのか、など細部は検証していないので、興味をもった方はいろいろ試していただければと思います。