Keras-TF で、長方形の入力画像

長方形の画像でも普通に Keras-TF で処理できるよ、というサンプル。

前提条件としては。

クラス0 : `images/a000.png` 〜 `images/a999.png` 
クラス1 : `images/b000.png` 〜 `images/b999.png` 
クラス2 : `images/c000.png` 〜 `images/c999.png` 

という画像があって、サイズはいずれも 幅64pix, 高さ36pix。グレイスケール。

具体的には下表のような画像を用意した：

|クラス|画像(横に10枚、縦に3枚連結したもの)|
|:--|:--|
|0|![image.png](https://qiita-image-store.s3.amazonaws.com/0/6854/c719db17-c65f-27e1-5c7e-35f72939d4d0.png)|
|1|![image.png](https://qiita-image-store.s3.amazonaws.com/0/6854/f16846e5-5234-776f-d862-80f0c5ac2825.png)|
|2|![image.png](https://qiita-image-store.s3.amazonaws.com/0/6854/c052325f-1471-1151-d6b9-dcdce033229f.png)|

教師データとして 600枚×3クラス( 000〜599 )
テストデータとして 400枚×3クラス( 600〜999 )
利用した。

```Python:Python3.6
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
import numpy as np
import random
import cv2
import os

batch_size = 128
num_classes = 3
epochs = 20

# input image dimensions
img_rows, img_cols = 36, 64
train_count = 600
test_count = 400
types = [chr(c+ord("a")) for c in range(num_classes)]


def srces(x0, c):
    s = []
    for t in types:
        for x in range(c):
            s.append("images/%s%03d.png" % (t, (x+x0)))
    random.shuffle(s)
    return s


def x_matrix(srces):
    arrays = [cv2.imread(fn, -1).reshape(1, img_rows, img_cols, 1)
              for fn in srces]
    return np.concatenate(arrays).astype('float32') / 255


def type_of(fn):
    return ord(os.path.basename(fn)[0]) - ord("a")


def y_matrix(srces, num_classes):
    arrays = [np.array(type_of(fn)) for fn in srces]
    y = np.vstack(arrays).reshape(len(arrays),)
    return keras.utils.to_categorical(y, num_classes)


def prepare_model(input_shape):
    model = Sequential()

    model.add(Conv2D(32, kernel_size=(3, 3),
                     activation='relu',
                     input_shape=input_shape))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(num_classes, activation='softmax'))

    model.compile(loss=keras.losses.categorical_crossentropy,
                  optimizer=keras.optimizers.Adadelta(),
                  metrics=['accuracy'])
    return model


def main():
    train_srces = srces(0, train_count)
    test_srces = srces(train_count, test_count)

    x_train = x_matrix(train_srces)
    y_train = y_matrix(train_srces, num_classes)
    x_test = x_matrix(test_srces)
    y_test = y_matrix(test_srces, num_classes)

    input_shape = (img_rows, img_cols, 1)

    model = prepare_model(input_shape)

    model.fit(x_train, y_train,
              batch_size=batch_size,
              epochs=epochs,
              verbose=1,
              validation_data=(x_test, y_test))
    score = model.evaluate(x_test, y_test, verbose=0)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])


main()
```

最終出力は

```text
Test loss: 0.02713265500109022
Test accuracy: 0.9908333333333333
```

という感じになった。
簡単なデータだったので 100% にならなかったのはちょっと残念。
モデルを追い込んでいないので仕方ないか。