Jetson Nano + Pytorchでゴルフ場が衛星画像に写っているかを識別してみるの続編です。
Tellusのチュートリアルにあるように上記のページで予測に使った画像は学習にも使われたものだったので、精度に問題があるかもしれません。
予測の検証には学習で使われていなかった未知の画像を取得する必要があります。
で、チュートリアルの後半では画像取得でTellusOSを使っていますが、ここでは未知の画像を用意するために他の手段で衛星画像を取得し、それを使って検証してみます。
下記の記述にないDockerコマンドを使ったデータのコピーやJupyter Notebookの開き方などは上記のページを参考にしてください。
学習モデルは上記で作成したgolf-model.pth を使います。
衛星画像のダウンロード
LANDSAT-8という衛星からのデータです。
産総研のLandbrowserを使ってダウンロードします。
ドラッグして移動します、今回は「近畿地方」にします。
近畿地方を含む広大な画像の一部にズームインしたものです。
LANDSAT-8は様々な波長(バンド)の電波(電磁波)を使って取得した画像データを提供してくれます。
Saveをクリックしてダウンロードウィンドウを表示。
今回はこの中からバンド2、3,4をダウンロードしておきます。
ダウンロードした衛星画像から合成画像を作成
ダウンロードした衛星画像はtif形式の、大きくてひたすら暗いだけのモノトーン画像です。
これを合成してトゥルーカラーの合成画像を作成します。
QGISを使うという手もありますが、ちと手間がかかります。
衛星画像教育用ソフトウェアEISEIという解析用ツールを使ってみます(PDF内のリンクからダウンロード)。
余談ですが、EISEI開発に参加している「公益財団法人日本宇宙少年団」って何でしょう?なんか、少年探偵団みたいで楽しそうすね(^^)。団員資格に性別・年齢問わず….とありますねぇ。ふむふむ。
閑話休題
EISEIをインストールして起動したら、メニュの「色合成」をクリック。
画像をRGBとして読み込むメニュが開きます。
今回は合成画像を作ることが目的なので、青:バンド2の画像、緑:バンド3の画像、赤:バンド4の画像データを読み込みます。
ダウンロードした衛星画像はこんな感じのモノトーンです。
メニュの「色・明るさ」を選んで、「自動」を使って明るくしておきます。
こんな合成画像ができます。
EISEIには画像の切り出し機能もありますが、サイズを指定できないので、別途画像処理専用アプリを使います。
とりあえず名前を付けてPNGファイルで保存しておきます。
画像の切り出しはJetsonでやることにして、保存した画像はSAMBAなどでコピーしておきます。
Jetson(Jetpack/Ubuntu)の画像アプリを使ってポジ・ネガ用の画像を切り出す
Ubuntuで使える画像処理アプリで名の通ったものではGIMPやPintaがあります。
今回は切り出しだけなので軽量なPintaを使います。
メニュのSoftwareからPintaを インストール。
Pintaを起動して保存済みの衛星画像を読み込んでおきます。
目的のゴルフ場は大阪の北部郊外にやたらにあります。
ゴルフ場のあるあたりで画像を300%程度に拡大して、ゴルフ場をある程度の大きさで捉えてRectangle Selectを選びます。
矩形領域で囲って枠の青いコントロールポイントをドラッグすれば拡大できます。
256 x 256 の矩形枠にします。
Crop to Selection を選んで、この矩形領域を切り出します。
これをpositive画像として保存しておきます(new_positive.png)。
同じことを、今度はゴルフ場が無い場所でやって、negative画像として保存しておきます(new_negative.png)。
2つの画像をコンテナにコピーしてJupyter Notebook で検証してみます
コードはこんな感じ。
保存しておいたモデルファイルを読み込んでリグレッションします。
非推奨だったtorchvision の transforms.Scale は transforms.Resize に変更しておきました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
from PIL import Image import torch.nn as nn from torch.autograd import Variable import torch import torchvision.transforms as transforms import torchvision.models as models import torchvision model = models.resnet18(pretrained=True) model.fc = nn.Linear(512, 2) model_path = './golf-model.pth' model.load_state_dict(torch.load(model_path)) model.eval() imsize = 256 loader = transforms.Compose([transforms.Resize(imsize), transforms.ToTensor()]) def image_loader(image_name): image = Image.open(image_name).convert("RGB") image = loader(image) image = Variable(image, requires_grad=True) image = image.unsqueeze(0) return image m = nn.Softmax(dim=1) |
予測
1 2 |
image = image_loader('./new-positive.png') print(m(model(image))) |
1 2 |
image = image_loader('./new_negative.png') print(m(model(image))) |
こんな感じ。
positive画像では66%程度の確からしさで「ゴルフ場が有るかもね」となっていますが、
negative画像では93%の確からしさで「ゴルフ場なんて無いよ」と言い切ってます(^^)。
予測の精度が下がる原因はいくつかあるようです。
1つはチュートリアルにあるように学習データは比較的寒い季節の画像が大量に含まれているため、温かい時期の芝生が青い画像のデータは予測されにくいということ。
左の画像(new_image)はGoogleMapsの航空写真からのものですが、夏場のゴルフ場。
右の画像は同じゴルフ場で、衛星画像(new_image2)ですが冬場のものです。
確からしさ(右の値)は全然違っています。
もう一つは画像に占めるゴルフ場のサイズが小さい場合です。
訓練用のデータでは比較的大きいサイズで写り込んでいます。
例えばこんな感じ。
以下のように同じゴルフ場でも写り込んでいる比率で確からしさは違ってきます。
今回使ったLandsat-8の画像は2021-01-15T01:34:56Zのものです。
画像に占めるゴルフ場のサイズが小さい場合
確からしさは21%程度。
1 |
tensor([[0.7844, 0.2156]], grad_fn=<SoftmaxBackward>) |
大きい場合。
確からしさは91%です。
1 |
tensor([[0.0829, 0.9171]], grad_fn=<SoftmaxBackward>) |
以上
Leave a Reply