转载请注明作者和出处:https://blog.csdn.net/qq_28810395
Python版本: Python3.x
运行平台: Windows 10
IDE: Pycharm profession 2019
如有需要数据集或整个工程文件的可以进行关注cai_5158046回复口罩识别进行获取。
在此只做简单利用Tensorflow进行口罩识别的程序实现,不做算法讲解,具体概念请移步下面链接。
https://blog.csdn.net/qq_28810395/article/details/107401125
数据集(200幅戴口罩图片,200幅没戴口罩图片)如下。
mask
nomask
对于深度网络模型训练,仅仅200的训练集完全不足够进行训练,在此只是测试讲解,所以200样本集足够用于展示流程。
具体代码展示
搭建网络,训练模型。
import os, shutil, random, glob
#添加tensorflow的库
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
#添加matplotlib的库进行界面可视化
import matplotlib.pyplot as plt
#变量
resize = 224 #输入图片尺寸参数
total_num = 200 #训练集总计和
train_num = 180 #训练集实际训练数字,20的验证集
epochs = 5 #迭代次数
batch_size = 8 #每次训练多少张
# -----------------------------------------------------------------------------
dir_data = './train/' #训练集路径
dir_mask = os.path.join(dir_data, 'mask') #戴口罩文件夹路径
dir_nomask = os.path.join(dir_data, 'nomask') #没带口罩文件夹路径
#健壮性的断言
assert os.path.exists(dir_mask), 'Could not find ' + dir_mask
assert os.path.exists(dir_nomask), 'Could not find ' + dir_nomask
#定义了文件指针对整个文件夹遍历一遍,将图像读出来
fpath_mask = [os.path.abspath(fp) for fp in glob.glob(os.path.join(dir_mask, '*.jpg'))]
fpath_nomask = [os.path.abspath(fp) for fp in glob.glob(os.path.join(dir_nomask, '*.jpg'))]
#文件数
num_mask = len(fpath_mask)
num_nomask = len(fpath_nomask)
#设置标签
label_mask = [0] * num_mask
label_nomask = [1] * num_nomask
print('#mask: ', num_mask)
print('#nomask: ', num_nomask)
#划分多少为验证集
RATIO_TEST = 0.1
num_mask_test = int(num_mask * RATIO_TEST)
num_nomask_test = int(num_nomask * RATIO_TEST)
# train
fpath_train = fpath_mask[num_mask_test:] + fpath_nomask[num_nomask_test:]
label_train = label_mask[num_mask_test:] + label_nomask[num_nomask_test:]
# validation
fpath_vali = fpath_mask[:num_mask_test] + fpath_nomask[:num_nomask_test]
label_vali = label_mask[:num_mask_test] + label_nomask[:num_nomask_test]
num_train = len(fpath_train)
num_vali = len(fpath_vali)
print(num_train)
print(num_vali)
#预处理
def preproc(fpath, label):
image_byte = tf.io.read_file(fpath)
image = tf.io.decode_image(image_byte)
image_resize = tf.image.resize_with_pad(image, 224, 224) #缩放到224*224
image_norm = tf.cast(image_resize, tf.float32) / 255. #归一化
label_onehot = tf.one_hot(label, 2)
return image_norm, label_onehot
dataset_train = tf.data.Dataset.from_tensor_slices((fpath_train, label_train)) #将数据进行预处理
dataset_train = dataset_train.shuffle(num_train).repeat() #打乱顺序
dataset_train = dataset_train.map(preproc, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset_train = dataset_train.batch(batch_size).prefetch(tf.data.experimental.AUTOTUNE) #一批次处理多少份
dataset_vali = tf.data.Dataset.from_tensor_slices((fpath_vali, label_vali))
dataset_vali = dataset_vali.shuffle(num_vali).repeat()
dataset_vali = dataset_vali.map(preproc, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset_vali = dataset_vali.batch(batch_size).prefetch(tf.data.experimental.AUTOTUNE)
# -----------------------------------------------------------------------------
# AlexNet 算法模型
model = keras.Sequential(name='Alexnet')
#第1层
model.add(layers.Conv2D(filters=96, kernel_size=(11,11),
strides=(4,4), padding='valid',
input_shape=(resize,resize,3),
activation='relu'))
model.add(layers.BatchNormalization())
#第1层池化
model.add(layers.MaxPooling2D(pool_size=(3,3),
strides=(2,2),
padding='valid'))
#第2层
model.add(layers.Conv2D(filters=256, kernel_size=(5,5),
strides=(1,1), padding='same',
activation='relu'))
model.add(layers.BatchNormalization())
#第2层池化
model.add(layers.MaxPooling2D(pool_size=(3,3),
strides=(2,2),
padding='valid'))
#第3层
model.add(layers.Conv2D(filters=384, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
#第4层
model.add(layers.Conv2D(filters=384, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
#第5层
model.add(layers.Conv2D(filters=256, kernel_size=(3,3),
strides=(1,1), padding='same',
activation='relu'))
model.add(layers.MaxPooling2D(pool_size=(3,3),
strides=(2,2), padding='valid'))
#第6,7,8层
model.add(layers.Flatten())
model.add(layers.Dense(4096, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(4096, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1000, activation='relu'))
model.add(layers.Dropout(0.5))
# Output Layer
model.add(layers.Dense(2, activation='softmax'))
# Training 优化器
model.compile(loss='categorical_crossentropy',
optimizer='sgd', #梯度下降法
metrics=['accuracy'])
history = model.fit(dataset_train,
steps_per_epoch = num_train//batch_size,
epochs = epochs, #迭代次数
validation_data = dataset_vali,
validation_steps = num_vali//batch_size,
verbose = 1)
#评分标准
# scores = model.evaluate(train_data, train_label, verbose=1)
scores = model.evaluate(dataset_train, steps=num_train//batch_size, verbose=1)
print(scores)
# scores = model.evaluate(test_data, test_label, verbose=1)
scores = model.evaluate(dataset_vali, steps=num_vali//batch_size, verbose=1)
print(scores)
#保存模型
model.save('./model/mask.h5')
# Record loss and acc
history_dict = history.history
train_loss = history_dict['loss']
train_accuracy = history_dict['accuracy']
val_loss = history_dict['val_loss']
val_accuracy = history_dict['val_accuracy']
# Draw loss
plt.figure()
plt.plot(range(epochs), train_loss, label='train_loss')
plt.plot(range(epochs), val_loss, label='val_loss')
plt.legend()
plt.xlabel('epochs')
plt.ylabel('loss')
# Draw acc
plt.figure()
plt.plot(range(epochs), train_accuracy, label='train_accuracy')
plt.plot(range(epochs), val_accuracy, label='val_accuracy')
plt.legend()
plt.xlabel('epochs')
plt.ylabel('accuracy')
# Display
plt.show()
print('Task finished')
程序中只采用了5次迭代,具体工程也是远远不够的,在此也同样仅仅做流程说明,所以不做要求。
显示loss
显示acc
import cv2
from tensorflow.keras.models import load_model
resize = 224
label = ('戴口罩!', '没戴口罩')
image = cv2.resize(cv2.imread('./test/test1.jpg'),(resize,resize))
image = image.astype("float") / 255.0
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
model = load_model('./model/mask.h5')
predict = model.predict(image)
i = predict.argmax(axis=1)[0]
print(label[i])