2016-07-06 4 views
2

Dies ist mein allererstes Mal mit einem Convolutional Neuronal Networks und Tensorflow.Erste Schritte mit Tensorflow - Split-Bild in Sub-Bilder

Ich versuche, ein konvolutionelles neuronales Netzwerk zu implementieren, das in der Lage ist extrahiert Schiffe aus Digital Retinal Images. Ich arbeite mit dem öffentlich verfügbaren Drive database (Bilder sind im .tif-Format).

Da meine Bilder sehr groß sind, ist es meine Idee, sie in Subbilder der Größe 28x28x1 zu teilen (Die "1" ist der grüne Kanal, der einzige, den ich brauche). Um den Trainingssatz zu erstellen, schneide ich zufällig einen 28x28 Stapel von jedem Bild und trainiere das Netzwerk auf diesem Satz.

Nun möchte ich mein geschultes Netzwerk auf einem der großen Bilder in der Datenbank testen (das heißt, ich möchte das Netzwerk auf ein vollständiges Auge anwenden). Da mein Netzwerk auf Teilbildern der Größe 28x28 trainiert wird, ist die Idee, das Auge in ‚n‘ Teilbildern zu teilen, gibt sie das Netz werfen, sie wieder zusammenzusetzen und das Ergebnis als Show in Abb1 zeigen:

Fig1

Ich versuchte mit einigen Funktionen wie: tf.extract_image_pathces oder tf.train.batch, aber ich würde gerne wissen, was die richtige Methode ist, dies zu tun.

Unten ist ein Ausschnitt meines Codes. Die Funktion, wo ich stecken bin, ist split_image(image)

import numpy 
import os 
import random 

from PIL import Image 
import tensorflow as tf 

BATCH_WIDTH = 28; 
BATCH_HEIGHT = 28; 

NUM_TRIALS = 10; 

class Drive: 
    def __init__(self,train): 
     self.train = train 

class Dataset: 
    def __init__(self, inputs, labels): 
     self.inputs = inputs 
     self.labels = labels 
     self.current_batch = 0 

    def next_batch(self): 
     batch = self.inputs[self.current_batch], self.labels[self.current_batch] 
     self.current_batch = (self.current_batch + 1) % len(self.inputs) 
     return batch 


#counts the number of black pixel in the batch 
def mostlyBlack(image): 
    pixels = image.getdata() 
    black_thresh = 50 
    nblack = 0 
    for pixel in pixels: 
     if pixel < black_thresh: 
      nblack += 1 

    return nblack/float(len(pixels)) > 0.5 

#crop the image starting from a random point 
def cropImage(image, label): 
    width = image.size[0] 
    height = image.size[1] 
    x = random.randrange(0, width - BATCH_WIDTH) 
    y = random.randrange(0, height - BATCH_HEIGHT) 
    image = image.crop((x, y, x + BATCH_WIDTH, y + BATCH_HEIGHT)).split()[1] 
    label = label.crop((x, y, x + BATCH_WIDTH, y + BATCH_HEIGHT)).split()[0] 
    return image, label 

def split_image(image): 

    ksizes_ = [1, BATCH_WIDTH, BATCH_HEIGHT, 1] 
    strides_ = [1, BATCH_WIDTH, BATCH_HEIGHT, 1] 

    input = numpy.array(image.split()[1]) 
    #input = tf.reshape((input), [image.size[0], image.size[1]]) 

    #input = tf.train.batch([input],batch_size=1) 
    split = tf.extract_image_patches(input, padding='VALID', ksizes=ksizes_, strides=strides_, rates=[1,28,28,1], name="asdk") 

#creates NUM_TRIALS images from a dataset 
def create_dataset(images_path, label_path): 
    files = os.listdir(images_path) 
    label_files = os.listdir(label_path) 

    images = []; 
    labels = []; 
    t = 0 
    while t < NUM_TRIALS: 
     index = random.randrange(0, len(files)) 
     if files[index].endswith(".tif"): 
      image_filename = images_path + files[index] 
      label_filename = label_path + label_files[index] 
      image = Image.open(image_filename) 
      label = Image.open(label_filename) 
      image, label = cropImage(image, label) 
      if not mostlyBlack(image): 
       #images.append(tf.convert_to_tensor(numpy.array(image))) 
       #labels.append(tf.convert_to_tensor(numpy.array(label))) 
       images.append(numpy.array(image)) 
       labels.append(numpy.array(label)) 

       t+=1 

    image = Image.open(images_path + files[1]) 
    split_image(image) 

    train = Dataset(images, labels) 
    return Drive(train) 
+1

Ich denke, du meinst Patch und nicht Batch ist es verwirrend. – jean

Antwort

1

Sie eine Kombination aus reshape und transpose Anrufe verwenden können, um ein Bild in Kacheln zu schneiden:

def split_image(image3, tile_size): 
    image_shape = tf.shape(image3) 
    tile_rows = tf.reshape(image3, [image_shape[0], -1, tile_size[1], image_shape[2]]) 
    serial_tiles = tf.transpose(tile_rows, [1, 0, 2, 3]) 
    return tf.reshape(serial_tiles, [-1, tile_size[1], tile_size[0], image_shape[2]]) 

wo image3 ist ein 3-dimensionales Tensor (zB ein image) und tile_size ist ein Wertepaar [H, W], das die Größe einer Kachel angibt. Der Ausgang ist ein Tensor mit der Form [B, H, W, C]. In Ihrem Fall würde der Anruf sein:

tiles = split_image(image, [28, 28]) 

was zu einem Tensor mit Form [B, 28, 28, 1]. Sie können auch das Originalbild von den Fliesen wieder zusammenzusetzen, indem sie diese in umgekehrter Funktion:

def unsplit_image(tiles4, image_shape): 
    tile_width = tf.shape(tiles4)[1] 
    serialized_tiles = tf.reshape(tiles4, [-1, image_shape[0], tile_width, image_shape[2]]) 
    rowwise_tiles = tf.transpose(serialized_tiles, [1, 0, 2, 3]) 
    return tf.reshape(rowwise_tiles, [image_shape[0], image_shape[1], image_shape[2]])) 

Wo tiles4 eine 4D Tensor Form ist [B, H, W, C] und image_shape die Form des ursprünglichen Bildes ist. In Ihrem Fall könnte der Anruf sein:

image = unsplit_image(tiles, tf.shape(image)) 

Beachten Sie, dass dies nur funktioniert, wenn die Bildgröße durch die Kachelgröße teilbar ist. Wenn das nicht der Fall ist Sie auf das nächste Vielfache der Fliesengröße Pad Ihr Bild benötigen:

def pad_image_to_tile_multiple(image3, tile_size, padding="CONSTANT"): 
    imagesize = tf.shape(image3)[0:2] 
    padding_ = tf.to_int32(tf.ceil(imagesize/tile_size)) * tile_size - imagesize 
    return tf.pad(image3, [[0, padding_[0]], [0, padding_[1]], [0, 0]], padding) 

, die Sie als solche bezeichnen würde:

image = pad_image_to_tile_multiple(image, [28,28]) 

Dann entfernen Sie die Stützpolster durch Spleißen, nachdem Sie wieder zusammen das Bild von Fliesen:

image = image[0:original_size[0], 0:original_size[1], :]