Pour la segmentation d'image à l'aide du Deep Learning --Création d'un petit lot d'images à partir d'une grande image
[ISBI challenge 2012(Segmentation of neuronal structures in EM stacks)] Les données d'image des cellules répertoriées dans (http://brainiac2.mit.edu/isbi_challenge/home) sont utilisées. Vous pouvez télécharger des données d'image en vous inscrivant sur la page d'accueil. Contient l'image de la cellule d'origine et les données pré-peintes. Sur la base de ces données, nous préparerons les données d'apprentissage afin de peindre automatiquement dans l'apprentissage supervisé.
Les données d'image d'origine sont de taille (512, 512) (ci-dessus). Divisez cette image en tailles (256, 256). Tout d'abord, lisez les données.
from skimage import io
import tensorflow as tf
import glob
dir_name = "./data/train"
paths_train_img = glob.glob(dir_name + "/train_image*")
paths_train_label = glob.glob(dir_name + "/train_label*")
train_images = []
train_labels = []
for path in paths_train_img[:-5]:
train_images.append(io.imread(path)/255.0)
path = path.replace('image', 'labels')
train_labels.append(io.imread(path)/255.0)
train_images = train_images[..., tf.newaxis]
train_labels = train_labels[..., tf.newaxis]
# print(train_images.shape)
# (25, 512, 512, 1)
train_images contient l'image de cellule d'origine et train_labels contient les données pré-peintes. Les images correspondent à train_images [i] et train_labels [i]. J'ai ajouté un axe en utilisant tf.newaxis pour une utilisation ultérieure dans tensorflow.
Maintenant, coupez l'image et créez un lot. Utilisez tf.image.extract_patches pour cela. Concernant tf.image.extract_patches, la Page officielle était difficile à comprendre personnellement, mais article sur le débordement de la pile //stackoverflow.com/questions/40731433/understanding-tf-extract-image-patches-for-extracting-patches-from-an-image) était facile à comprendre.
ksize_rows = 256
ksize_cols = 256
strides_rows = 256
strides_cols = 256
ksizes = [1, ksize_rows, ksize_cols, 1]
strides = [1, strides_rows, strides_cols, 1]
rates = [1, 1, 1, 1]
padding='VALID'
def make_patches(images):
image_patches = tf.image.extract_patches(images, ksizes, strides, rates, padding)
#correctifs d'image(25, 2, 2, 65536)Forme.
# 65536=256*À 256(256, 256)L'image de taille est stockée dans une dimension.
patches = []
for patch in image_patches:
for i in range(patch.shape[0]):
for j in range(patch.shape[1]):
patch2 = patch[i,j,:]
patch2 = np.reshape(patch2, [ksize_rows, ksize_cols,1])
# (i,j)Lot d'images de la position de(256, 256)Remodeler à la forme de
patches.append(patch2)
patches = np.array(patches)
return patches
train_image_patches = make_patches(train_images)
train_label_patches = make_patches(train_labels)
En utilisant make_patches ci-dessus, l'image peut être coupée en images par lots de taille (256, 256). Puisque l'image originale était de 25 images de taille (512, 512), train_image_patches et train_label_images contiennent respectivement 100 données d'image de taille (256, 256).
Nous effectuerons une augmentation des données à l'aide de Image Data Generator. ImageDataGenerator gonfle l'image à l'aide de transformations telles que la rotation, le zoom et le retournement de l'image. Passez la valeur maximale telle que la rotation et le zoom comme argument. Vous pouvez également attribuer une fonction de prétraitement d'image pour prétraiter l'image avant diverses conversions. Dans l'exemple ci-dessous, le bruit gaussien est ajouté en tant que prétraitement.
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import skimage
def add_noise(img):
output_img = skimage.util.random_noise(img, var=0.01, clip=False)
return np.array(output_img)
SEED1 = 1
batch_size = 2
args={
"rotation_range":0.2,
"width_shift_range":0.2,
"height_shift_range":0.2,
"zoom_range":0.2,
"shear_range":0.2,
"vertical_flip":True,
"horizontal_flip":True,
"fill_mode":"reflect",
"preprocessing_function":add_noise
}
image_data_generator = ImageDataGenerator(**args
).flow(train_image_patches, batch_size=batch_size, seed=SEED1)
args.pop("preprocessing_function")
label_data_generator = ImageDataGenerator(**args
).flow(train_label_patches, batch_size=batch_size, seed=SEED1)
Puisque je ne veux pas ajouter de bruit aux données de réponse correctes pré-peintes, j'ai supprimé preproccesing_function d'arguments pour créer label_data_generator. En créant image_data_generator et label_data_genrator en utilisant la même graine, l'image d'origine et l'image pré-peinte correspondent correctement.
Enfin, rassemblez-les dans un seul générateur.
def my_image_mask_generator(image_data_generator, mask_data_generator):
train_generator = zip(image_data_generator, mask_data_generator)
for (img, mask) in train_generator:
yield (img, mask)
my_generator = my_image_mask_generator(image_data_generator, label_data_generator)
Jetons un coup d'œil aux données d'image réellement créées.
plt.figure(dpi=100)
for i in range(3):
img, mask = next(my_generator)
plt.subplot(2, 3, i + 1)
plt.imshow(img[0, :,:,0], cmap="gray")
plt.subplot(2, 3, i + 4)
plt.imshow(mask[0, :, :, 0], cmap="gray")
plt.axis('off')
plt.show()
Vous pouvez voir qu'un lot d'images a été créé dans lequel l'image de cellule d'origine et l'image pré-peinte sont correctement associées. De plus, l'image ressemble à une partie de celle-ci est réfléchie vers le bord. Cela est dû au fait que ImageDataGenerator est défini sur "fill_mode": "refléter", de sorte que les blancs qui se produisent lorsque l'image est déplacée en parallèle sont complétés en mode de réflexion.
Vous avez maintenant regroupé les images et complété vos données pour la segmentation des images. La prochaine fois, nous effectuerons un apprentissage en profondeur en utilisant ces données d'image.
Recommended Posts