2017-02-08 8 views
1

Я хотел бы узнать изображения отпечатков пальцев, которые были бинаризованы с использованием PIL для тензорного потока. Я пытаюсь изучить бинаризованное изображение, поэтому форма неправильная.(Изменить) Tensorflow tflearn Вопросы обучения двоичного изображения

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) 

Я попытался использовать numpy изменить размеры. Однако, следующая ошибка повторяется.

Ошибка заключается в следующем. ValueError: Невозможно подавать значение формы (64,224,224) для тензора u'input/X: 0 ', который имеет форму (?, 224, 224, 3)

В чем проблема?

+0

Это большая модель и, похоже, опирается на маринованные данные. Не могли бы вы попытаться собрать [минимальный и полный пример проблемы] (http://stackoverflow.com/help/mcve)? –

+0

Я отправил пример. –

ответ

0

Проблема с вашей формой ввода - она ​​не соответствует входному слою.

Входной слой определяется в create_vggnet():

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

Таким образом, вы ожидать None (== любые) раз (224, 224, 3), то есть 224x224 х RGB (3 канала). И вы передаете 64 (ваш размер партии) раз 224x224.

Есть два исправления:

1) (вероятно, более расточительным) - расширяющие изображения в RGB.

Итак, после того, как вы преобразуете изображение в 'L' (легкость, то есть уровни серого), а затем выполните бинаризацию, сначала преобразуйте его в RGB. Затем вы можете преобразовать его в 'F'

(См: http://effbot.org/imagingbook/image.htm и 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) (менее расточительным, но вы меняете сети немного (только входной слой) - поэтому он может утверждают, что это «больше не VGG 16»). Вы можете изменить уровень ввода на 1 канал.

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

К сожалению, shape=[None, 224, 224] не работает (ошибка что-то о «Тензор должна быть 4D»). Таким образом, мы имеем форму (224, 224, 1) для одного входного значения.

Так что вам нужно сделать изображения имеют дополнительное измерение:

def pil_to_nparray(pil_image): 
    pil_image.load() 

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

или (может быть, даже лучше):

def pil_to_nparray(pil_image): 
    pil_image.load() 

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

(последняя версия выглядит более прямым, вы точно знаете, что это) Но это работает только в том случае, если входное изображение 224x224, а expand_dims всегда будет добавлять дополнительное измерение для любого размера.

+0

Решено. Спасибо за ответ. –