-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhyperspectral_image_generator.py
162 lines (141 loc) · 7.79 KB
/
hyperspectral_image_generator.py
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
from random import sample
import geopandas as gpd
import numpy as np
from keras.utils import to_categorical
from numpy import ceil, floor
from rasterio import open
from rasterio.mask import mask
from shapely.geometry import box
from skimage.io import imread
from image_functions import categorical_label_from_full_file_name, preprocessing_image_ms
def hyperspectral_image_generator(files, class_indices, batch_size=32, image_mean=None,
rotation_range=0, shear_range=0, scale_range=1,
transform_range=0, horizontal_flip=False,
vertical_flip=False, crop=False, crop_size=None, filling_mode='edge',
speckle_noise=None):
while True:
# select batch_size number of samples without replacement
batch_files = sample(files, batch_size)
# get one_hot_label
batch_Y = categorical_label_from_full_file_name(batch_files,
class_indices)
# array for images
batch_X = []
# loop over images of the current batch
for idx, input_path in enumerate(batch_files):
image = np.array(imread(input_path), dtype=float)
if image_mean is not None:
mean_std_data = np.loadtxt(image_mean, delimiter=',')
image = preprocessing_image_ms(image, mean_std_data[0], mean_std_data[1])
# process image
image = augmentation_image_ms(image, rotation_range=rotation_range, shear_range=shear_range,
scale_range=scale_range,
transform_range=transform_range, horizontal_flip=horizontal_flip,
vertical_flip=vertical_flip, warp_mode=filling_mode)
if speckle_noise is not None:
from skimage.util import random_noise
image_max = np.max(np.abs(image), axis=(0, 1))
image /= image_max
image = random_noise(image, mode='speckle', var=speckle_noise)
image *= image_max
if crop:
if crop_size is None:
crop_size = image.shape[0:2]
image = crop_image(image, crop_size)
# put all together
batch_X += [image]
# convert lists to np.array
X = np.array(batch_X)
Y = np.array(batch_Y)
yield(X, Y)
def hyperspectral_image_generator_jp2(files, shape_file, class_indices_column, batch_size=32, image_mean=None,
rotation_range=0, shear_range=0, scale_range=1,
transform_range=0, horizontal_flip=False,
vertical_flip=False, crop_size=None, filling_mode='edge',
speckle_noise=None):
geometry_df = gpd.read_file(shape_file)
centroids = geometry_df['geometry'].values
class_indices = geometry_df[class_indices_column].values.astype(int)
number_of_classes = class_indices.max()
files_centroids = list(zip(files*len(centroids), list(centroids)*len(files), list(class_indices)*len(files)))
while True:
# select batch_size number of samples without replacement
batch_files = sample(files_centroids, batch_size)
# get one_hot_label
batch_Y = []
# array for images
batch_X = []
# loop over images of the current batch
for idx, (rf, polycenter, label) in enumerate(batch_files):
raster_file = open(rf)
mask_polygon = box(max(polycenter.coords.xy[0][0] - raster_file.transform[0] * crop_size[0] * 2,
raster_file.bounds.left),
max(polycenter.coords.xy[1][0] - raster_file.transform[4] * crop_size[1] * 2,
raster_file.bounds.bottom),
min(polycenter.coords.xy[0][0] + raster_file.transform[0] * crop_size[0] * 2,
raster_file.bounds.right),
min(polycenter.coords.xy[1][0] + raster_file.transform[4] * crop_size[1] * 2,
raster_file.bounds.top))
image, out_transform = mask(raster_file, shapes=[mask_polygon], crop=True, all_touched=True)
image = np.transpose(image, (1, 2, 0))
if image_mean is not None:
mean_std_data = np.loadtxt(image_mean, delimiter=',')
image = preprocessing_image_ms(image.astype(np.float64), mean_std_data[0], mean_std_data[1])
# process image
image = augmentation_image_ms(image, rotation_range=rotation_range, shear_range=shear_range,
scale_range=scale_range,
transform_range=transform_range, horizontal_flip=horizontal_flip,
vertical_flip=vertical_flip, warp_mode=filling_mode)
if speckle_noise is not None:
from skimage.util import random_noise
image_max = np.max(np.abs(image), axis=(0, 1))
image /= image_max
image = random_noise(image, mode='speckle', var=speckle_noise)
image *= image_max
image = crop_image(image, crop_size)
# put all together
batch_X += [image]
batch_Y += [to_categorical(label, num_classes=number_of_classes)]
# convert lists to np.array
X = np.array(batch_X)
Y = np.array(batch_Y)
yield(X, Y)
def augmentation_image_ms(image, rotation_range=0, shear_range=0, scale_range=1, transform_range=0,
horizontal_flip=False, vertical_flip=False, warp_mode='edge'):
from skimage.transform import AffineTransform, SimilarityTransform, warp
from numpy import deg2rad, flipud, fliplr
from numpy.random import uniform, random_integers
from random import choice
image_shape = image.shape
# Generate image transformation parameters
rotation_angle = uniform(low=-abs(rotation_range), high=abs(rotation_range))
shear_angle = uniform(low=-abs(shear_range), high=abs(shear_range))
scale_value = uniform(low=abs(1 / scale_range), high=abs(scale_range))
translation_values = (random_integers(-abs(transform_range), abs(transform_range)),
random_integers(-abs(transform_range), abs(transform_range)))
# Horizontal and vertical flips
if horizontal_flip:
# randomly flip image up/down
if choice([True, False]):
image = flipud(image)
if vertical_flip:
# randomly flip image left/right
if choice([True, False]):
image = fliplr(image)
# Generate transformation object
transform_toorigin = SimilarityTransform(scale=(1, 1), rotation=0, translation=(-image_shape[0], -image_shape[1]))
transform_revert = SimilarityTransform(scale=(1, 1), rotation=0, translation=(image_shape[0], image_shape[1]))
transform = AffineTransform(scale=(scale_value, scale_value), rotation=deg2rad(rotation_angle),
shear=deg2rad(shear_angle), translation=translation_values)
# Apply transform
image = warp(image, ((transform_toorigin) + transform) + transform_revert, mode=warp_mode, preserve_range=True)
return image
def crop_image(image, target_size):
x_crop = min(image.shape[0], target_size[0])
y_crop = min(image.shape[1], target_size[1])
midpoint = [ceil(image.shape[0] / 2), ceil(image.shape[1] / 2)]
out_img = image[int(midpoint[0] - ceil(x_crop / 2)):int(midpoint[0] + floor(x_crop / 2)),
int(midpoint[1] - ceil(y_crop / 2)):int(midpoint[1] + floor(y_crop / 2)),
:]
assert list(out_img.shape[0:2]) == target_size
return out_img