2017-02-08 7 views
1

Ich möchte Fingerabdrücke lernen, die mit PIL für den Tensorfluss binarisiert wurden. Ich versuche ein binarisiertes Bild zu lernen, also ist die Form nicht richtig.(Ändern) Tensorflow tflearn Binäre Bildlernfragen

from __future__ import division, print_function, absolute_import 
import pickle 
import numpy as np 
from PIL import Image 
import tflearn 
import tensorflow as tf 
from tflearn.layers.core import input_data, dropout, fully_connected 
from tflearn.layers.conv import conv_2d, max_pool_2d 
from tflearn.layers.estimator import regression 


def load_image(img_path): 
    img = Image.open(img_path) 

    return img 


def resize_image(in_image, new_width, new_height, out_image=None, 
       resize_mode=Image.ANTIALIAS): 
    img = in_image.resize((new_width, new_height), resize_mode) 

    if out_image: 
     img.save(out_image) 

    return img 


def pil_to_nparray(pil_image): 
    pil_image.load() 

    return np.asarray(pil_image, dtype="float32") 


def binarization(in_img, threshold): 
    im = in_img.convert('L') 
    for i in range(im.size[0]): 
     for j in range(im.size[1]): 
      if im.getpixel((i,j)) > threshold: 
       im.putpixel((i,j), 255) 
      else: 
       im.putpixel((i,j), 0) 
    return im.convert('F') 


def load_data(datafile, num_clss, save=True, save_path='dataset.pkl'): 
    train_list = open(datafile,'r') 
    labels = [] 
    images = [] 
    for line in train_list: 
     tmp = line.strip().split(' ') 
     fpath = tmp[0] 
     print(fpath) 
     img = load_image(fpath) 
     img = binarization(img, 128) 
     img = resize_image(img, 224, 224) 
     np_img = pil_to_nparray(img) 
     images.append(np_img) 

     index = int(tmp[1]) 
     label = np.zeros(num_clss) 
     label[index] = 1 
     labels.append(label) 
    if save: 
     pickle.dump((images, labels), open(save_path, 'wb')) 

    return images, labels 


def load_from_pkl(dataset_file): 
    X, Y = pickle.load(open(dataset_file, 'rb')) 
    return X, Y 


def create_vggnet(num_classes): 
    # Building 'VGGNet' 
    network = input_data(shape=[None, 224, 224, 3], name='input') 
    network = conv_2d(network, 64, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 64, filter_size=3, strides=1, activation='relu') 
    network = max_pool_2d(network, kernel_size=2, strides=2) 
    network = conv_2d(network, 128, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 128, filter_size=3, strides=1, activation='relu') 
    network = max_pool_2d(network, 2, strides=2) 

    network = conv_2d(network, 256, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 256, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 256, filter_size=3, strides=1, activation='relu') 
    network = max_pool_2d(network, kernel_size=2, strides=2) 

    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = max_pool_2d(network, kernel_size=2, strides=2) 

    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = conv_2d(network, 512, filter_size=3, strides=1, activation='relu') 
    network = max_pool_2d(network, kernel_size=2, strides=2) 

    network = fully_connected(network, 4096, activation='relu') 
    network = dropout(network, 0.5) 
    network = fully_connected(network, 4096, activation='relu') 
    network = dropout(network, 0.5) 
    network = fully_connected(network, num_classes, activation='softmax') 

    network = regression(network, optimizer='adam', loss='categorical_crossentropy', 
         learning_rate=0.001) 

    return network 


def train(network, X, Y): 
    # Trainingeed data dictionary, with placeholders as keys, and data as values. 
    model = tflearn.DNN(network, checkpoint_path='model_vgg', 
         max_checkpoints=1, tensorboard_verbose=2, tensorboard_dir='output') 
    model.fit(X, Y, n_epoch=100, validation_set=0.1, shuffle=True, show_metric=True, 
       batch_size=64, snapshot_step=200, snapshot_epoch=False, run_id='vgg_fingerprint') 
    model.save('model_save.model') 


def predict(network, modelfile, images): 
    model = tflearn.DNN(network) 
    model.load(modelfile) 

    return model.predict(images) 


if __name__ == '__main__': 
    #image, label = load_data('train.txt', 5) 
    X, Y = load_from_pkl('dataset.pkl') 
    net = create_vggnet(5) 
    train(net, X, Y) 

Ich habe versucht, mit numpy die Abmessungen ändern ändern. Der folgende Fehler wird jedoch wiederholt.

Der Fehler lautet wie folgt. ValueError: Kann Wert der Form (64,224,224) für Tensor u'input/X: 0 'nicht einspeisen, der Form (?, 224, 224, 3)

hat

Was ist das Problem?

+0

Das ist ein großes Modell und sieht so aus, als ob es auf gebeizten Daten beruht. Könnten Sie versuchen, ein [minimales und vollständiges Beispiel des Problems] (http://stackoverflow.com/help/mcve) zusammenzustellen? –

+0

Ich habe ein Beispiel gepostet. –

Antwort

0

Das Problem liegt in Ihrer Eingabeform - sie stimmt nicht mit der Eingabeebene überein.

Die Eingangsschicht wird in create_vggnet() definiert:

def create_vggnet(num_classes): 
    # Building 'VGGNet' 
    network = input_data(shape=[None, 224, 224, 3], name='input') 

So erwarten Sie None (== vorhanden) mal (224, 224, 3), dh 224x224 x RGB (3 Kanäle). Und Sie übergeben 64 (Ihre Batch-Größe) mal 224x224.

Es gibt zwei Korrekturen:

1) (wahrscheinlich mehr verschwenderisch) - erweitern die Bilder zu RGB.

Also, nachdem Sie das Bild in 'L' (Helligkeit, das ist Graustufen) konvertieren und dann binär, konvertieren Sie es zuerst in RGB. Dann Sie es 'F'

umwandeln können (siehe: http://effbot.org/imagingbook/image.htm und How do I save a mode 'F' image? (Python/PIL))

def binarization(in_img, threshold): 
    im = in_img.convert('L') 
    for i in range(im.size[0]): 
     for j in range(im.size[1]): 
      if im.getpixel((i, j)) > threshold: 
       im.putpixel((i, j), 255) 
      else: 
       im.putpixel((i, j), 0) 
    return im.convert('RGB').convert('F') 

2) (weniger verschwenderisch, aber Sie Ihr Netzwerk ein Bit (nur die Eingangsschicht zu ändern) - so kann es argumentiert, dass dies "nicht mehr VGG 16 ist") Sie können die Eingabeschicht auf 1-Kanal umstellen.

def create_vggnet(num_classes): 
    # Building 'VGGNet' 
    network = input_data(shape=[None, 224, 224, 1], name='input') 

Leider shape=[None, 224, 224] funktioniert nicht (der Fehler ist etwas, über "Die Tensor sein 4D muss"). Wir haben also eine Form von (224, 224, 1) für einen einzelnen Eingabewert.

Sie müssen also die Bilder machen haben eine zusätzliche Dimension:

def pil_to_nparray(pil_image): 
    pil_image.load() 

    return np.expand_dims(np.asarray(pil_image, dtype="float32"), 2) 

oder (vielleicht sogar besser):

def pil_to_nparray(pil_image): 
    pil_image.load() 

    return np.asarray(pil_image, dtype="float32").reshape((224, 224, 1)) 

(letztere Version direkterer sieht, wissen Sie genau das, was does) Aber das funktioniert nur, wenn das Eingabebild 224x224 ist, während die expand_dims immer die zusätzliche Dimension hinzufügen würde, für jede Größe.

+0

Es ist gelöst. Danke für die Antwort. –

Verwandte Themen