卫星图像中的船舶检测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('
X:{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实例

相关推荐