[PYTHON] Geotag-Vorhersage aus Bildern mit DNN

Einführung

Dieses Mal möchte ich anhand eines trainierten Modells eine Geotag-Vorhersage aus einem Gebäudebild machen. Insbesondere in diesem Artikel habe ich mit dem Ziel begonnen, die Ausgabe mehrerer Beschriftungen für Breiten- und Längengrade aus dem Eingabebild zu verwenden.

Zu verwendende Daten

Die diesmal verwendeten Daten sind "European Cities 1M-Datensatz". http://image.ntua.gr/iva/datasets/ec1m/index.html

Verwenden Sie das Landmark-Set-Bild bzw. das Geotag auf dieser Site.

Bauumgebung

Die Implementierung in diesem Artikel verwendet Google Colaboratory. Die Einstellungen der verwendeten Umgebung sind unten aufgeführt.


import keras
from keras.utils import np_utils
from keras.models import Sequential, Model, load_model
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers.core import Dense, Dropout, Activation, Flatten
import numpy as np
from sklearn.model_selection import train_test_split
import os, zipfile, io, re
from PIL import Image
import glob
from tqdm import tqdm

from sklearn.model_selection import train_test_split
from keras.applications.xception import Xception
from keras.applications.resnet50 import ResNet50
from keras.layers.pooling import GlobalAveragePooling2D
from keras.optimizers import Adam, Nadam

Vorverarbeitung

Hier wird als Vorverarbeitung die Verarbeitung mit Breiten- und Längengradbezeichnungen durchgeführt. Dieses Mal lernen wir den Breiten- und Längengrad getrennt als Beschriftungen, sodass wir sie so verarbeiten, dass sie leicht als Liste abgerufen werden können.


with open("landmark/ec1m_landmarks_geotags.txt") as f:
    label=f.readlines()
    for i in label:
        ans=i.split(' ')
        ans[1]=ans[1].replace('\n','')
        print(ans)

Ausgabe


['41.4134', '2.153']
['41.3917', '2.16472']
['41.3954', '2.16177']
['41.3954', '2.16177']
['41.3954', '2.16156']
['41.3899', '2.17428']
['41.3953', '2.16184']
['41.3953', '2.16172']
['41.3981', '2.1645']
.....
.....

Datenerfassung

Die Bildgröße beträgt 100 Datensatz in Array konvertieren Beschriften Sie das Bild, ohne den Breiten- und Längengrad zu trennen


X = []
Y = []
image_size=100

with open("landmark/ec1m_landmarks_geotags.txt") as f:
    label=f.readlines()

    dir = "landmark/ec1m_landmark_images"
    files = glob.glob(dir + "/*.jpg ")
    for index,file in tqdm(enumerate(files)):
        image = Image.open(file)
        image = image.convert("RGB")
        image = image.resize((image_size, image_size))
        data = np.asarray(image)
        X.append(data)
        Y.append(label[index])
 
X = np.array(X)
Y = np.array(Y)

Ausgabe


927it [00:08, 115.29it/s]

Jede Form ist so
X.shape,Y.shape
((927, 100, 100, 3), (927,))

Als nächstes in Zug teilen, testen, gültig Teilen Sie hier Breiten- und Längengrade

y0=[]  #Latitude-Label
y1=[]  #Längengradetikett

for i in Y:
    ans=i.split(' ')
    ans[1]=ans[1].replace('\n','')
    y0.append(float(ans[0]))
    y1.append(float(ans[1]))

y0=np.array(y0)
y1=np.array(y1)

#x(train,test)Teilt
X_train, X_test = train_test_split(X, random_state = 0, test_size = 0.2)
print(X_train.shape,  X_test.shape) 

#(741, 100, 100, 3) (186, 100, 100, 3)

#y0,y1(train,test)Teilt
y_train0,y_test0,y_train1, y_test1 = train_test_split(y0,y1,
                                                      random_state = 0,
                                                      test_size = 0.2)
print(y_train0.shape,  y_test0.shape) 
print(y_train1.shape,  y_test1.shape)

#(741,) (186,)
#(741,) (186,)

#Datentypkonvertierung und -normalisierung
X_train = X_train.astype('float32') / 255
X_test = X_test.astype('float32') / 255

#x(train,valid)Teilt
X_train, X_valid= train_test_split(X_train, random_state = 0, test_size = 0.2)
print(X_train.shape,  X_valid.shape) 

#(592, 100, 100, 3) (149, 100, 100, 3)

#y0,y1(train,valid)Teilt
y_train0, y_valid0,y_train1, y_valid1= train_test_split(y_train0,y_train1,
                                                        random_state = 0,
                                                        test_size = 0.2)

print(y_train0.shape,  y_valid0.shape) 
print(y_train1.shape,  y_valid1.shape) 

#(592,) (149,)
#(592,) (149,)

Modellbau

Dieses Mal verwenden wir das trainierte Modell von Xception unter Bezugnahme auf den folgenden Artikel. https://qiita.com/ha9kberry/items/314afb56ee7484c53e6f#データ取得

Ich wollte es mit anderen Modellen versuchen, also werde ich auch versuchen, Resnet zu verwenden.


#xception model
base_model = Xception(
    include_top = False,
    weights = "imagenet",
    input_shape = None
)

#resnet model
base_model = ResNet50(
    include_top = False,
    weights = "imagenet",
    input_shape = None
)

Geben Sie am Ende des Regressionsproblems einen vorhergesagten Wert ein Bereiten Sie die Etikettenausgabe für Breiten- und Längengrade vor

x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions1 = Dense(1,name='latitude')(x)
predictions2 = Dense(1,name='longitude')(x)

Setzen Sie Vorhersagen1 und Vorhersagen2 in die Ausgabe ein. Andere sind wie im Referenzartikel Dieses Mal werden wir Adam und Nadam als Optimierer verwenden.


model = Model(inputs = base_model.input, outputs = [predictions1,predictions2])

#Frieren Sie bis zu 108 Schichten ein
for layer in model.layers[:108]:
    layer.trainable = False

    #Unfreeze Batch Normalization
    if layer.name.startswith('batch_normalization'):
        layer.trainable = True
    if layer.name.endswith('bn'):
        layer.trainable = True

#Lernen Sie ab Ebene 109
for layer in model.layers[108:]:
    layer.trainable = True

# layer.Kompilieren nach dem Setzen trainierbar
model.compile(
    optimizer = Adam(),
    #optimizer=Nadam(),
    loss = {'latitude':root_mean_squared_error,
            'longitude':root_mean_squared_error
        }
)


Lernen


history = model.fit( X_train,   #decode_train
                    {'latitude': y_train0,
                     'longitude':y_train1},
                    batch_size=64,
                    epochs=50,
                    validation_data=(X_valid,    decode_valid
                                     {'latitude' :y_valid0,
                                      'longitude':y_valid1}),
                    )

Ausgabe



Epoch 1/50
10/10 [==============================] - 4s 409ms/step - loss: 0.6146 - latitude_loss: 0.4365 - longitude_loss: 0.1782 - val_loss: 1.6756 - val_latitude_loss: 1.3430 - val_longitude_loss: 0.3326
Epoch 2/50
10/10 [==============================] - 4s 404ms/step - loss: 0.5976 - latitude_loss: 0.4415 - longitude_loss: 0.1562 - val_loss: 0.7195 - val_latitude_loss: 0.5987 - val_longitude_loss: 0.1208

...
...

Zeichnen Sie die Ergebnisse

import matplotlib.pyplot as plt


plt.figure(figsize=(18,6))

# loss
plt.subplot(1, 2, 1)
plt.plot(history.history["latitude_loss"], label="latitude_loss", marker="o")
plt.plot(history.history["longitude_loss"], label="longitude_loss", marker="o")
#plt.yticks(np.arange())
#plt.xticks(np.arange())
plt.ylabel("loss")
plt.xlabel("epoch")
plt.title("")
plt.legend(loc="best")
plt.grid(color='gray', alpha=0.2)

plt.show()

Ergebnis ダウンロード (9).png

Auswertung


#batch size 64  Adam
scores = model.evaluate(X_test,{'latitude' :y_test0,
                                'longitude':y_test1}, 
                             verbose=1)

print("total loss:\t{0}".format(scores[0]))
print("latitude loss:\t{0}".format(scores[1]))
print("longtitude loss:{0}".format(scores[2]))

Ausgabe



total loss:	0.7182420492172241
latitude loss:	0.6623533964157104
longtitude loss:0.05588864907622337

Prognose


# show image, prediction and actual label
for i in range(10,12):
    plt.figure(figsize=(10,10))
    print('latitude:{} \tlongititude{}'.format(
        prediction[0][i],
        prediction[1][i],
        ))

    plt.imshow(X_test[i].reshape(100, 100, 3))
    plt.show()

latitude:[39.69221] longititude[2.2188098] ダウンロード (10).png

latitude:[39.728386] longititude[2.224149] ダウンロード (11).png

Es gibt solche Zahlen, aber wenn sie auf der Karte (Google Map) ausgedrückt werden, befindet sie sich wie unten gezeigt mitten im Meer, was nicht ausreicht, um sie zu verwenden.

image.png

Vergleich mit anderen Parametern

Verwendete Parameter Total loss latitude_loss longtitude_loss
Xception , Adam 0.7182 0.6623 0.0558
Xception , Nadam 0.3768 0.1822 0.1946
Resnet , Adam 0.7848 0.7360 0.0488
Resnet , Nadam 49.6434 47.2652 2.3782
Resnet,Adam,AutoEncoder 1.8299 1.6918 0.13807

schließlich

In dieser Studie wurde festgestellt, dass die Kombination von Xception und Nadam am genauesten ist. In Zukunft werde ich ein anderes Modell verwenden oder ein Modell von Grund auf neu erstellen

Referenz, Zitat

Datensatz

Publications Conferences Y. Avrithis, Y. Kalantidis, G. Tolias, E. Spyrou. Retrieving Landmark and Non-Landmark Images from Community Photo Collections. In Proceedings of ACM Multimedia (MM 2010), Firenze, Italy, October 2010.

Journals Y. Kalantidis, G. Tolias, Y. Avrithis, M. Phinikettos, E. Spyrou, P. Mylonas, S. Kollias. VIRaL: Visual Image Retrieval and Localization. In Multimedia Tools and Applications (to appear), 2011.

Artikel

--https: //qiita.com/ha9kberry/items/314afb56ee7484c53e6f # Übersicht

Recommended Posts

Geotag-Vorhersage aus Bildern mit DNN
Laden Sie Bilder von "Irasutoya" mit Scrapy herunter
Laden Sie Bilder von der URL mit Pillow in Python 3
Laden Sie Bilder mithilfe von Anfragen herunter
Extrahieren Sie Zeichen aus Bildern mithilfe der Zeichenerkennungs-API von docomo
Sammeln Sie Bilder mit icrawler
Finden Sie Kartenillustrationen aus Bildern mithilfe der Feature-Point-Anpassung
Kompilieren Sie Tesseract für Tess4J, um Bilder mit CentOS zu transkribieren
Speichern Sie Bilder mit Python3-Anforderungen
Sofort von Google-Bildern abkratzen!
Vorhersage von Wolkenbildern mit convLSTM
Kategorisieren Sie Katzenbilder mit ChainerCV