import cv2
import numpy as np
import pandas as pd
import keras
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Activation, Flatten, GlobalAveragePooling2D
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Input
from keras.optimizers import SGD, RMSprop
from keras.callbacks import ModelCheckpoint, EarlyStopping
import sys
#Two head - one for number and one for digit with constant positions
#params
list_a= ['0','1','2','3','4','5','6','7','8','9']
list_b= ['A','B','C']
dx= 20
dy= 50
font_scale= 1
batch_size= 32
epochs= 20
patience = 10
model_name= 'model.h5'
input_dim= (80,120,3)
def generate_random_plate_number():
img= np.zeros(input_dim, np.uint8)
rand_indx_b= np.random.randint(len(list_b))
letter_str1= list_b[rand_indx_b]
#print('letter_str',letter_str) #
cv2.putText(img, letter_str1, (0,dy), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255,255,255), thickness=2)
rand_indx_a= np.random.randint(len(list_a))
number_str1= list_a[rand_indx_a]
#print('number_str',number_str) #
cv2.putText(img, number_str1, (2*dx,dy), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255,255,255), thickness=2)
y1= np.zeros((len(list_b)), np.int32)
y2= np.zeros((len(list_a)), np.int32)
y1[list_b.index(letter_str1)]= 1
y2[list_a.index(number_str1)]= 1
#print('y1', y1) #
#print('y2', y2) #
return img,y1,y2
def batch_generator(batch_size):
while True:
image_list = []
y1_list = []
y2_list = []
for i in range(batch_size):
img,y1,y2= generate_random_plate_number()
image_list.append(img)
y1_list.append(y1)
y2_list.append(y2)
image_arr = np.array(image_list, dtype=np.float32)
y1_arr = np.array(y1_list, dtype=np.int32)
y2_arr = np.array(y2_list, dtype=np.int32)
#print('image_arr.shape', image_arr.shape) #
#print('y1_arr.shape', y1_arr.shape) #
#print('y2_arr.shape', y2_arr.shape) #
yield(image_arr, {'output1': y1_arr, 'output2': y2_arr} )
def get_model():
network_input = Input(shape=input_dim)
conv1= Conv2D(32, (3, 3), padding='same')(network_input)
pool1= MaxPooling2D(pool_size=(2, 2))(conv1)
act1= Activation('relu')(pool1)
conv2= Conv2D(32, (3, 3), padding='same')(act1)
pool2= MaxPooling2D(pool_size=(2, 2))(conv2)
act2= Activation('relu')(pool2)
conv3= Conv2D(64, (3, 3), padding='same')(act2)
pool3= MaxPooling2D(pool_size=(2, 2))(conv3)
act3= Activation('relu')(pool3)
conv4= Conv2D(64, (3, 3), padding='same')(act3)
pool4= MaxPooling2D(pool_size=(2, 2))(conv4)
act4= Activation('relu')(pool4)
tail= GlobalAveragePooling2D()(act4)
#global_pool= GlobalAveragePooling2D()(act4)
#tail= Dense(128)(global_pool)
#add heads
head1= Dense(len(list_b))(tail)
softmax1= Activation('softmax', name='output1')(head1)
head2= Dense(len(list_a))(tail)
softmax2= Activation('softmax', name='output2')(head2)
model = Model(input = network_input, output = [softmax1,softmax2])
model.compile(optimizer = RMSprop(1e-3),
loss = {'output1': 'categorical_crossentropy', 'output2': 'categorical_crossentropy'})
#print(model.summary()) #
#sys.exit() #
return model
def train():
model= get_model()
callbacks = [
EarlyStopping(monitor='val_loss', patience=patience, verbose=0),
ModelCheckpoint('model_temp.h5', monitor='val_loss', save_best_only=True, verbose=0),
]
history = model.fit_generator(
generator=batch_generator(batch_size),
nb_epoch=epochs,
samples_per_epoch=1*batch_size,
validation_data=batch_generator(batch_size),
nb_val_samples=1*batch_size,
verbose=2,
callbacks=callbacks)
model.save_weights(model_name)
pd.DataFrame(history.history).to_csv('train_history.csv', index=False)
Задача (не реальная) на картинке (80,120,3) в константных местах стоят(разные) цифра и буква, соответственно создаем общее 'тело' и 2 'головы'(для буквы и цифры), но чего то так не учится. Есть какие то соображения или типа задача weakly supervised и её сложно\невозможно в такой постановке решить?