衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

衛星圖像是數據科學家可以使用的最豐富的數據源之一。本文將使用Kaggle上的機器學習數據集(https://www.kaggle.com/rhammell/ships-in-satellite-imagery),此機器學習數據:

  • 包括4000個80x80 RGB圖像,標記為“ship”或“no-ship”分類,值為1或0。
  • 機器學習數據集為.png圖像,圖像文件名遵循特定格式:{label} __ {scene id} __ {longitude} _ {latitude} .png
  • longitude_latitude:圖像中心點的經度和緯度座標
  • dataset也作為JSON格式的文本文件分發,包含:data,label,scene_ids和location list
  • 單個圖像的像素值數據存儲為19200個整數的列表:第一個6400包含紅色通道,下一個6400包含綠色,最後的6400包含藍色。
  • labels,scene_ids和位置中的索引i處的列表值,每個對應於數據列表中的第i個圖像
  • 類標籤:“ship”類包括1000個圖像,靠近單個船體的中心。“no-ship”類包括3000幅圖像,1/3是不同土地覆蓋特徵的隨機抽樣(不包括船舶的任何部分),1/3是“部分船隻”,1/3是先前被錯誤標記的圖像。

我們想要實現的目標:檢測衛星圖像中船舶的位置,可用於解決以下問題:監控港口活動和供應鏈分析。

導入Python庫

import json, sys, random
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Flatten, Activation
from keras.layers import Dropout
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.utils import np_utils
from keras.optimizers import SGD
import keras.callbacks
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt
衛星圖像中的船舶檢測Python實例

讀取和準備數據

除了常規的Keras: sequence、density、Flatten、Activation和Dropout也將使用Conv2D和MaxPooling2D。現在讓我們研究機器學習數據集:

# Download and study the data set
f = open(r'../ships-in-satellite-imagery/shipsnet.json')
dataset = json.load(f)
f.close()
input_data = np.array(dataset['data']).astype('uint8')
output_data = np.array(dataset['labels']).astype('uint8')
# the data set contains 4000 images.
# One image is represented as a vector of lenght 19200 elements = [(image size: 80x80=6400) * 3 RGB bands]
input_data.shape
衛星圖像中的船舶檢測Python實例

(4000, 19200)

input_data
衛星圖像中的船舶檢測Python實例

# to be able to read an image we need to reshape the array/input_data
n_spectrum = 3 # color chanel RGB
weight = 80
height = 80
X = input_data.reshape([-1, n_spectrum, weight, height])
X[0].shape
衛星圖像中的船舶檢測Python實例

(3, 80, 80)

# get one channel 
pic = X[3]
red_spectrum = pic[0]
green_spectrum = pic[1]
blue_spectrum = pic[2]
衛星圖像中的船舶檢測Python實例

在3個通道上繪製照片:

plt.figure(2, figsize = (5*3, 5*1))
plt.set_cmap('jet')
#show each channel
plt.subplot(1, 3, 1)
plt.imshow(red_spectrum)
plt.subplot(1, 3, 2)

plt.imshow(green_spectrum)
plt.subplot(1, 3, 3)
plt.imshow(blue_spectrum)
plt.show()
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

如果X[0]的一些照片可能具有所有3個bands RGB相同,不要灰心,只要嘗試另一個X[3]。

我們的輸出是4000個元素的向量:

output_data.shape

(4000,)

output_data

array([1, 1, 1, ..., 0, 0, 0], dtype=uint8)

np.bincount(output_data)

array([3000, 1000])

為keras準備數據

首先對標籤進行分類編碼:

# output encoding
y = np_utils.to_categorical(output_data, 2)
衛星圖像中的船舶檢測Python實例

shuffle所有索引:

# shuffle all indexes
indexes = np.arange(4000)
np.random.shuffle(indexes)
衛星圖像中的船舶檢測Python實例

選擇X_train,y_train:

X_train = X[indexes].transpose([0,2,3,1])
y_train = y[indexes]
衛星圖像中的船舶檢測Python實例

當然還有歸一化:

# normalization 
X_train = X_train/255
衛星圖像中的船舶檢測Python實例

訓練模型/神經網絡

np.random.seed(42)
# network design
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', input_shape=(80, 80, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) #40x40
model.add(Dropout(0.25))
model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) #20x20
model.add(Dropout(0.25))

model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) #10x10
model.add(Dropout(0.25))
model.add(Conv2D(32, (10, 10), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) #5x5
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2, activation='softmax'))
衛星圖像中的船舶檢測Python實例

設置優化器

# optimization setup
sgd = SGD(lr=0.01, momentum=0.9, nesterov=True)
model.compile(
loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])

衛星圖像中的船舶檢測Python實例

訓練神經網絡

# training
model.fit(
X_train,
y_train,
batch_size=32,
epochs=18,
validation_split=0.2,
shuffle=True,
verbose=2)
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

在圖像上應用模型和搜索

image = Image.open(r'../ships-in-satellite-imagery/scenes/sfbay_1.png')
pix = image.load()
plt.imshow(image)
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

'plt.imshow(image)'如果你想快速瀏覽一下,為了能夠正確使用它,我們需要創建一個向量:

n_spectrum = 3
width = image.size[0]
height = image.size[1]
# creat vector
picture_vector = []
for chanel in range(n_spectrum):
for y in range(height):
for x in range(width):
picture_vector.append(pix[x, y][chanel])
picture_vector = np.array(picture_vector).astype('uint8')
picture_tensor = picture_vector.reshape([n_spectrum, height, width]).transpose(1, 2, 0)
plt.figure(1, figsize = (15, 30))
plt.subplot(3, 1, 1)

plt.imshow(picture_tensor)
plt.show()
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

現在讓我們在圖像上搜索船隻

picture_tensor = picture_tensor.transpose(2,0,1)
# Search on the image
def cutting(x, y):
area_study = np.arange(3*80*80).reshape(3, 80, 80)
for i in range(80):
for j in range(80):
area_study[0][i][j] = picture_tensor[0][y+i][x+j]
area_study[1][i][j] = picture_tensor[1][y+i][x+j]
area_study[2][i][j] = picture_tensor[2][y+i][x+j]
area_study = area_study.reshape([-1, 3, 80, 80])
area_study = area_study.transpose([0,2,3,1])
area_study = area_study / 255
sys.stdout.write('\rX:{0} Y:{1} '.format(x, y))
return area_study
def not_near(x, y, s, coordinates):
result = True
for e in coordinates:
if x+s > e[0][0] and x-s < e[0][0] and y+s > e[0][1] and y-s < e[0][1]:
result = False
return result
def show_ship(x, y, acc, thickness=5):
for i in range(80):
for ch in range(3):
for th in range(thickness):
picture_tensor[ch][y+i][x-th] = -1
for i in range(80):
for ch in range(3):
for th in range(thickness):
picture_tensor[ch][y+i][x+th+80] = -1

for i in range(80):
for ch in range(3):
for th in range(thickness):
picture_tensor[ch][y-th][x+i] = -1

for i in range(80):
for ch in range(3):
for th in range(thickness):
picture_tensor[ch][y+th+80][x+i] = -1
step = 10; coordinates = []
for y in range(int((height-(80-step))/step)):
for x in range(int((width-(80-step))/step) ):
area = cutting(x*step, y*step)
result = model.predict(area)
if result[0][1] > 0.90 and not_near(x*step,y*step, 88, coordinates):

coordinates.append([[x*step, y*step], result])
print(result)
plt.imshow(area[0])
plt.show()
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例

正如您所看到的那樣:它確實分類為具有直線和明亮像素的船舶圖像。

再試一次:

衛星圖像中的船舶檢測Python實例

現在讓我們理解標籤並在圖像上找到它們:

for e in coordinates:
show_ship(e[0][0], e[0][1], e[1][0][1])
#picture_tensor = picture_tensor.transpose(2,0,1)
picture_tensor = picture_tensor.transpose(1,2,0)
picture_tensor.shape
衛星圖像中的船舶檢測Python實例

(1777, 2825, 3)

plt.figure(1, figsize = (15, 30))
plt.subplot(3,1,1)
plt.imshow(picture_tensor)
plt.show()
衛星圖像中的船舶檢測Python實例

衛星圖像中的船舶檢測Python實例


分享到:


相關文章: