Zur Bildsegmentierung mit Deep Learning --Erstellen eines kleinen Bildstapels aus einem großen Bild
[ISBI challenge 2012(Segmentation of neuronal structures in EM stacks)] Die Bilddaten der in (http://brainiac2.mit.edu/isbi_challenge/home) aufgeführten Zellen werden verwendet. Sie können Bilddaten herunterladen, indem Sie sich auf der Homepage registrieren. Enthält das ursprüngliche Zellenbild und vorgemalte Daten. Basierend auf diesen Daten werden wir die Lerndaten vorbereiten, um das überwachte Lernen automatisch zu malen.
Die ursprünglichen Bilddaten sind (512, 512) groß (oben). Teilen Sie dieses Bild in Größen (256, 256). Lesen Sie zuerst die Daten.
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 enthält das ursprüngliche Zellenbild und train_labels enthält die vorgemalten Daten. Die Bilder entsprechen train_images [i] und train_labels [i]. Ich habe eine Achse mit tf.newaxis für die spätere Verwendung im Tensorflow hinzugefügt.
Schneiden Sie nun das Bild aus und erstellen Sie einen Stapel. Verwenden Sie dazu tf.image.extract_patches. In Bezug auf tf.image.extract_patches war die offizielle Seite persönlich schwer zu verstehen, aber Artikel über Stapelüberlauf //stackoverflow.com/questions/40731433/understanding-tf-extract-image-patches-for-extracting-patches-from-an-image) war leicht zu verstehen.
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)
#Bild-Patches(25, 2, 2, 65536)Gestalten.
# 65536=256*Bei 256(256, 256)Das Größenbild wird eindimensional gespeichert.
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)Bildstapel der Position von(256, 256)Umformen in die Form von
patches.append(patch2)
patches = np.array(patches)
return patches
train_image_patches = make_patches(train_images)
train_label_patches = make_patches(train_labels)
Mit make_patches oben kann das Bild in Stapelbilder mit einer Größe von (256, 256) geschnitten werden. Da das Originalbild 25 Bilder der Größe (512, 512) hatte, enthalten train_image_patches und train_label_images 100 Bilddaten der Größe (256, 256).
Wir werden die Datenerweiterung mit Image Data Generator durchführen. ImageDataGenerator bläst das Bild mithilfe von Transformationen wie Drehen, Zoomen und Spiegeln auf. Übergeben Sie den Maximalwert wie Drehung und Zoom als Argument. Sie können auch eine Funktion für die Bildvorverarbeitung angeben, um die Bildvorverarbeitung vor verschiedenen Konvertierungen durchzuführen. Im folgenden Beispiel wird Gaußsches Rauschen als Vorbehandlung hinzugefügt.
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)
Da ich den vorgemalten korrekten Antwortdaten kein Rauschen hinzufügen möchte, habe ich preproccesing_function aus args entfernt, um label_data_generator zu erstellen. Wenn Sie image_data_generator und label_data_genrator mit demselben Startwert erstellen, stimmen das Originalbild und das vorgemalte Bild korrekt überein.
Zum Schluss setzen Sie sie zu einem Generator zusammen.
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)
Werfen wir einen Blick auf die tatsächlich erstellten Bilddaten.
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()
Sie können sehen, dass ein Bildstapel erstellt wurde, in dem das ursprüngliche Zellenbild und das vorgemalte Bild korrekt zugeordnet sind. Außerdem sieht das Bild so aus, als würde ein Teil davon zum Rand hin reflektiert. Dies liegt daran, dass der ImageDataGenerator auf "fill_mode": "reflektieren" gesetzt ist, sodass die Leerzeichen, die beim parallelen Verschieben des Bildes auftreten, im Reflektionsmodus ergänzt werden.
Sie haben jetzt Bilder gestapelt und Ihre Daten für die Bildsegmentierung aufgefüllt. Das nächste Mal werden wir anhand dieser Bilddaten tiefes Lernen durchführen.
Recommended Posts