需求:判断手写ld的指令
训练模型:
from keras.models import Sequential
from keras import layers
from keras.layers import Dense, Dropout, Conv2D, MaxPooling2D, Flatten
import numpy
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
from keras.callbacks import ModelCheckpoint
#image->convolution->pooling->convolution->pooling->full connected->full connected(hidden layer) ->classifier
def defineModelAndGenerateModel():
model = Sequential() ## 定义cnn模型
model.add(Conv2D(32, (3,3), activation='relu',input_shape=(100,200,1))) ## 添加2D卷积层,32个过滤器,用3乘3过滤器,使用relu激活函数,指定输入图片尺寸
## ken 这里应该添加更多的层
model.add(MaxPooling2D(2,2)) ## 添加最大池化层
model.add(Conv2D(32, (3,3), activation='relu')) ## 添加2D卷积层,32个过滤器,用3乘3过滤器,使用relu激活函数,指定输入图片尺寸
model.add(MaxPooling2D(2,2)) ## 添加最大池化层
model.add(Conv2D(64, (3,3), activation='relu')) ## 添加2D卷积层,32个过滤器,用3乘3过滤器,使用relu激活函数,指定输入图片尺寸
model.add(MaxPooling2D(2,2)) ## 添加最大池化层
# drop out of max-pooling layer , drop out rate is 0.25 (0.5??)
#model.add(Dropout(0.25))
model.add(Dropout(0.5))
# flatten inputs from 2d to 1d
model.add(Flatten())
model.add(Dense(8, activation='softmax')) ## 添加全连结层,使用softmax激活函数,输出8种分类的可能性
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) ## 编译模型,rmsprop优化函数,分类交叉熵损失函数
train_datagen = ImageDataGenerator(rescale=1./255) ## 从目录里提取图片
train_generator = train_datagen.flow_from_directory(
'C:/hand-imgs', target_size=(100,200), #(120,205)
batch_size=10,
color_mode='grayscale',
class_mode='categorical'
)
#todo:训练之前应该将一部分训练中的数据挑选为validation用,用keras的split方法。
validation_generator= train_datagen.flow_from_directory(
'c:/hand-imgs-validate', target_size=(100,200),
batch_size=10,
color_mode='grayscale',
class_mode='categorical'
)
checkpoint = ModelCheckpoint('model-{epoch:03d}-{acc:03f}-{val_acc:03f}.h5', verbose=1, monitor='val_loss',save_best_only=True, mode='auto')
#调整参数
history = model.fit_generator( #开始训练模型
train_generator,
steps_per_epoch=100,
epochs=10,
validation_data= validation_generator,
callbacks=[checkpoint],
validation_steps=2)
model.save('hand_ld') ## 保存训练的模型(*以后做预测会用到)
return history
def showresult(history): ## 生成模型衡量的结果
plt.figure()
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
#plt.legend()
plt.show()
if __name__ == "__main__":
history= defineModelAndGenerateModel()
#showresult(history)
注意点:
- 多个池化层
- Dropout 0.2太小会产生过拟合,一般采用0.5
- 增加了checkpoint, 由于梯度下降的参数不同,顺着step增加,acc_val会变小。用checkpoint保存最高的acc_val
import os
import numpy as np
import cv2
from keras.models import Model
from keras.preprocessing import image as kimage
from keras.models import load_model
from procImg import procImage, drawImageResult
#const
#predictFile = "C:/hand-test/20200102170013216-2.jpg"
#predictFile = "C:/hand-backup/training/20191230165257965-6.jpg"
predictFile = "C:/hand-backup/validate/20200102101640083-28.jpg"
modlepath = 'model-008-0.966599-0.950000.h5'
def predict(image, model):
cv2.imwrite('cv2.jpeg', image) ##保存当前视频(图片)画面
kimg = kimage.load_img('cv2.jpeg', target_size=([100,200]), color_mode='grayscale') ## 转化为Keras能读取的数据格式
img_tensor = kimage.img_to_array(kimg)
img_tensor = np.expand_dims(img_tensor, axis=0)
predict = np.argmax(model.predict(img_tensor)) ## 使用模型预测,结果取8个分类结果中可能性最大的
return predict
def run():
model = load_model(modlepath) ## 读取保存的模型
image = cv2.imread(predictFile)
images = procImage(image)
predicts = []
for img in images:
ret = predict(img, model)
print(ret)
predicts.append(ret)
drawImageResult(image, predicts)
if __name__ == '__main__':
run()
cv2.waitKey()
创建模型的时候,前两位是训练产生的loss和acc,后两位是验证产生的val_loss和val_acc。