2017-02-08 9 views
1

テンソルの流れにPILを使用して2値化された指紋画像を学びたいと思います。 二値化された画像を学習しようとしていますので、形状が正しくありません。(変更)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:形状(?、224,224,3)のテンソルu'input/X:0 'の形状値(64,224,224)を入力できません。

問題は何ですか?

+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') 

だから、それは224x224 X RGB(3つのチャネル)である(3、224、224)None(==任意)時間を期待します。そして、64(バッチサイズ)倍の224x224を渡します。 RGBに画像を拡大 -

1)は(おそらくより無駄):

は、二つの修正があります。

したがって、画像を'L'(明度、つまりグレイレベル)に変換してから2値化した後、最初にRGBに変換してください。

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)(無駄なあまり、しかし、あなたはあなたのネットワークを変更しているビット(単に入力層) - それは、次のことができます。そして、あなたは'F'

に変換することができます(http://effbot.org/imagingbook/image.htmHow do I save a mode 'F' image? (Python/PIL)参照してください)これは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にする必要がある」程度のものである)は動作しません。したがって、1つの入力値に対して(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)) 

(後者のバージョンは、より直接的に見える、あなたは正確に何を知っていますdoes) しかし、これは入力画像が224x224の場合にのみ有効ですが、expand_dimsは常に任意のサイズの余分な寸法を追加します。

+0

解決済みです。答えてくれてありがとう。 –

関連する問題