这里写自定义目录标题
一、理解人脸图像特征提取的各种方法(至少包括HoG、Dlib和卷积神经网络特征);1.HOG①HOG定义:②HOG提取的图像信息
③HOG算法的基本流程2.Dlib①Dlib实现的人脸检测方法便是基于图像的Hog特征,结合支持向量机算法实现的人脸检测功能。该算法的大致思路如下:
③卷积神经网络特征
二、 掌握笑脸数据集(genki4k)正负样本的划分、模型训练和测试的过程(至少包括SVM、CNN),输出模型训练精度和测试精度(F1-score和ROC);1. [下载数据集的连接](https://github.com/truongnmt/smile-detection)2.根据猫狗数据集训练的方法来训练笑脸数据集1)首先将train_folder文件夹下俩个文件夹内的图片的名字做修改。(修改成猫狗的图片格式)2)图片分类3)作为健全性检查,让我们计算一下在每个训练分割中我们有多少图片(训练/验证/测试):4)卷积网络模型搭建5)图像生成器读取文件中数据,进行数据预处理。6)开始训练7)保存训练模型8)在培训和验证数据上绘制模型的损失和准确性(可视化界面)9)使用数据扩充10)使用数据扩充和退出来训练我们的网络11)保存模型12)在培训和验证数据上绘制模型的损失和准确性(可视化界面)
三、完成一个摄像头采集自己人脸、并对表情(笑脸和非笑脸)的实时分类判读(输出分类文字)的程序;1.基于上面卷积神经网络的笑脸识别2.基于Dlib的笑脸识别
四、将笑脸数据集换成口罩数据集,完成对口罩佩戴与否的模型训练,采取合适的特征提取方法,重新做上述2-3部。1.用上述同样的方法修改图片的命名格式2.卷积网络模型搭建3.图像生成器读取文件中数据,进行数据预处理。4.使用数据扩充5.使用数据扩充和退出来训练我们的网络6.保存模型7.在培训和验证数据上绘制模型的损失和准确性(可视化界面)8.实现摄像头口罩识别判断
一、理解人脸图像特征提取的各种方法(至少包括HoG、Dlib和卷积神经网络特征);
1.HOG
①HOG定义:
方向梯度直方图(Histogram of Oriented Gradient, HOG)是一种在计算机视觉和图像处理中用来进行物体检测的特征描述方法(特征描述方法:就是通过从图像中提取有用信息和丢弃无关信息来简化图像,并将信息运用于算法)。
②HOG提取的图像信息
a.特征描述方法从图像中提取有用信息 b.在图像中,物体的边缘和角落包含了关于物体形状的更多信息,也就是我们平时能看到的物体轮廓。如果能够提取出图像边缘和角落的信息,将非常有利于物体检测。 c.而对于图像的边缘和角落周围的梯度这个特征,变化幅度很大,所以在HOG特征描述方法中,使用梯度方向的分布(直方图)作为它的特征。
③HOG算法的基本流程
a.计算图像梯度 b.计算Cell中的梯度直方图 c.Block归一化 d.计算HOG特征
2.Dlib
①Dlib实现的人脸检测方法便是基于图像的Hog特征,结合支持向量机算法实现的人脸检测功能。该算法的大致思路如下:
1 )对正样本(即包含人脸的图像)数据集提取Hog特征,得到Hog特征描述子。 2 )对负样本(即不包含人脸的图像)数据集提取Hog特征,得到Hog特征描述子; 其中,负样本数据集中样本的数量要远远大于正样本数据集中的样本数,负样本图像可以 使用不含人脸的图片进行随机裁剪获取。 3 )利用支持向量机算法训练正负样本,显然这是一个二分类问题,可以得到训练后 的模型。 4 )利用该模型进行负样本难例检测,也就是难分样本挖掘( hard-negative mining ) ,以便提高最终模型的分类能力。具体思路为:对训练集里的负样本不断进行 缩放,直至与模板匹配为止,通过模板滑动窗口搜索匹配(该过程即多尺度检测过程),, 如果分类器误检出非人脸则截取该部分图像加入负样本中。 5 )结合难例样本重新训练模型,反复如此得到最终分类器模型。
③卷积神经网络特征
卷积神经网络最早是为了解决图像识别的问题,现在也用在时间序列数据和文本数据处理当中,卷积神经网络对于数据特征的提取不用额外进行,在对网络的训练的过程当中,网络会自动提取主要的特征.卷积神经网络直接用原始图像的全部像素作为输入,但是内部为非全连接结构.因为图像数据在空间上是有组织结构的,每一个像素在空间上和周围的像素是有关系的,和相距很远的像素基本上是没什么联系的,每个神经元只需要接受局部的像素作为输入,再将局部信息汇总就能得到全局信息. 权值共享和池化两个操作使网络模型的参数大幅的减少,提高了模型的训练效率.
二、 掌握笑脸数据集(genki4k)正负样本的划分、模型训练和测试的过程(至少包括SVM、CNN),输出模型训练精度和测试精度(F1-score和ROC);
1. 下载数据集的连接
将下载里面的datasets,放到D盘新建的smile中,
2.根据猫狗数据集训练的方法来训练笑脸数据集
1)首先将train_folder文件夹下俩个文件夹内的图片的名字做修改。(修改成猫狗的图片格式)
import os
import sys
def rename
():
path
=input
("请输入路径(例如D:\\\\picture):")
name
=input
("请输入开头名:")
startNumber
=input
("请输入开始数:")
fileType
=input
("请输入后缀名(如 .jpg、.txt等等):")
print
("正在生成以"+name+startNumber+fileType+
"迭代的文件名")
count
=0
filelist
=os.listdir
(path
)
for files
in filelist:
Olddir
=os.path.join
(path,files
)
if os.path.isdir
(Olddir
):
continue
Newdir
=os.path.join
(path,name+str
(count+int
(startNumber
))+fileType
)
os.rename
(Olddir,Newdir
)
count+
=1
print
("一共修改了"+str
(count
)+
"个文件")
rename
()
运行结果: 继续修改
2)图片分类
import os, shutil
original_dataset_dir1
= 'D:\\smile\\datasets\\train_folder\\1'
original_dataset_dir0
= 'D:\\smile\\datasets\\train_folder\\0'
base_dir
= 'D:\\smile1'
os.mkdir
(base_dir
)
train_dir
= os.path.join
(base_dir,
'train')
os.mkdir
(train_dir
)
validation_dir
= os.path.join
(base_dir,
'validation')
os.mkdir
(validation_dir
)
test_dir
= os.path.join
(base_dir,
'test')
os.mkdir
(test_dir
)
train_cats_dir
= os.path.join
(train_dir,
'smile')
os.mkdir
(train_cats_dir
)
train_dogs_dir
= os.path.join
(train_dir,
'unsmile')
os.mkdir
(train_dogs_dir
)
validation_cats_dir
= os.path.join
(validation_dir,
'smile')
os.mkdir
(validation_cats_dir
)
validation_dogs_dir
= os.path.join
(validation_dir,
'unsmile')
os.mkdir
(validation_dogs_dir
)
test_cats_dir
= os.path.join
(test_dir,
'smile')
os.mkdir
(test_cats_dir
)
test_dogs_dir
= os.path.join
(test_dir,
'unsmile')
os.mkdir
(test_dogs_dir
)
fnames
= ['smile.{}.jpg'.format
(i
) for i
in range
(1000
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir1, fname
)
dst
= os.path.join
(train_cats_dir, fname
)
shutil.copyfile
(src, dst
)
fnames
= ['smile.{}.jpg'.format
(i
) for i
in range
(500
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir1, fname
)
dst
= os.path.join
(validation_cats_dir, fname
)
shutil.copyfile
(src, dst
)
fnames
= ['smile.{}.jpg'.format
(i
) for i
in range
(500
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir1, fname
)
dst
= os.path.join
(test_cats_dir, fname
)
shutil.copyfile
(src, dst
)
fnames
= ['unsmile.{}.jpg'.format
(i
) for i
in range
(1000
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir0, fname
)
dst
= os.path.join
(train_dogs_dir, fname
)
shutil.copyfile
(src, dst
)
fnames
= ['unsmile.{}.jpg'.format
(i
) for i
in range
(500
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir0, fname
)
dst
= os.path.join
(validation_dogs_dir, fname
)
shutil.copyfile
(src, dst
)
fnames
= ['unsmile.{}.jpg'.format
(i
) for i
in range
(500
)]
for fname
in fnames:
src
= os.path.join
(original_dataset_dir0, fname
)
dst
= os.path.join
(test_dogs_dir, fname
)
shutil.copyfile
(src, dst
)
3)作为健全性检查,让我们计算一下在每个训练分割中我们有多少图片(训练/验证/测试):
print
('total training cat images:', len
(os.listdir
(train_cats_dir
)))
print
('total training dog images:', len
(os.listdir
(train_dogs_dir
)))
print
('total validation cat images:', len
(os.listdir
(validation_cats_dir
)))
print
('total validation dog images:', len
(os.listdir
(validation_dogs_dir
)))
print
('total test cat images:', len
(os.listdir
(test_cats_dir
)))
print
('total test dog images:', len
(os.listdir
(test_dogs_dir
)))
4)卷积网络模型搭建
from keras
import layers
from keras
import models
model
= models.Sequential
()
model.add
(layers.Conv2D
(32,
(3, 3
), activation
='relu',
input_shape
=(150, 150, 3
)))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(64,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Flatten
())
model.add
(layers.Dense
(512, activation
='relu'))
model.add
(layers.Dense
(1, activation
='sigmoid'))
model.summary
()
5)图像生成器读取文件中数据,进行数据预处理。
from keras
import optimizers
model.compile
(loss
='binary_crossentropy',
optimizer
=optimizers.RMSprop
(lr
=1e-4
),
metrics
=['acc'])
from keras.preprocessing.image
import ImageDataGenerator
train_datagen
= ImageDataGenerator
(rescale
=1./255
)
test_datagen
= ImageDataGenerator
(rescale
=1./255
)
train_generator
= train_datagen.flow_from_directory
(
train_dir,
target_size
=(150, 150
),
batch_size
=20,
class_mode
='binary')
validation_generator
= test_datagen.flow_from_directory
(
validation_dir,
target_size
=(150, 150
),
batch_size
=20,
class_mode
='binary')
6)开始训练
history = model.fit_generator
(
train_generator,
steps_per_epoch
=100,
epochs
=30,
validation_data
=validation_generator,
validation_steps
=50
)
7)保存训练模型
model.save
('D:\\smile1\\smiles_and_unsmiles_small_1.h5')
8)在培训和验证数据上绘制模型的损失和准确性(可视化界面)
import matplotlib.pyplot as plt
acc
= history.history
['acc']
val_acc
= history.history
['val_acc']
loss
= history.history
['loss']
val_loss
= history.history
['val_loss']
epochs
= range
(len
(acc
))
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.figure
()
plt.plot
(epochs, loss,
'bo', label
='Training loss')
plt.plot
(epochs, val_loss,
'b', label
='Validation loss')
plt.title
('Training and validation loss')
plt.legend
()
plt.show
()
9)使用数据扩充
datagen
= ImageDataGenerator
(
rotation_range
=40,
width_shift_range
=0.2,
height_shift_range
=0.2,
shear_range
=0.2,
zoom_range
=0.2,
horizontal_flip
=True,
fill_mode
='nearest')
from keras.preprocessing
import image
fnames
= [os.path.join
(train_cats_dir, fname
) for fname
in os.listdir
(train_cats_dir
)]
img_path
= fnames
[3
]
img
= image.load_img
(img_path, target_size
=(150, 150
))
x
= image.img_to_array
(img
)
x
= x.reshape
((1,
) + x.shape
)
i
= 0
for batch
in datagen.flow
(x, batch_size
=1
):
plt.figure
(i
)
imgplot
= plt.imshow
(image.array_to_img
(batch
[0
]))
i +
= 1
if i % 4
== 0:
break
plt.show
()
如果我们使用这种数据增强配置训练一个新网络,我们的网络将永远不会看到两次相同的输入。但是,输入它所看到的仍然是高度相关的,因为它们来自于少量的原始图像——我们无法产生新的信息,我们只能重新混合现有的信息。因此,这可能还不足以完全摆脱过度装修。继续战斗过度拟合,我们还将在密连接分类器之前向模型添加一个退出层:
model
= models.Sequential
()
model.add
(layers.Conv2D
(32,
(3, 3
), activation
='relu',
input_shape
=(150, 150, 3
)))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(64,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Flatten
())
model.add
(layers.Dropout
(0.5
))
model.add
(layers.Dense
(512, activation
='relu'))
model.add
(layers.Dense
(1, activation
='sigmoid'))
model.compile
(loss
='binary_crossentropy',
optimizer
=optimizers.RMSprop
(lr
=1e-4
),
metrics
=['acc'])
10)使用数据扩充和退出来训练我们的网络
train_datagen
= ImageDataGenerator
(
rescale
=1./255,
rotation_range
=40,
width_shift_range
=0.2,
height_shift_range
=0.2,
shear_range
=0.2,
zoom_range
=0.2,
horizontal_flip
=True,
)
test_datagen
= ImageDataGenerator
(rescale
=1./255
)
train_generator
= train_datagen.flow_from_directory
(
train_dir,
target_size
=(150, 150
),
batch_size
=32,
class_mode
='binary')
validation_generator
= test_datagen.flow_from_directory
(
validation_dir,
target_size
=(150, 150
),
batch_size
=32,
class_mode
='binary')
history = model.fit_generator
(
train_generator,
steps_per_epoch
=100,
epochs
=100,
validation_data
=validation_generator,
validation_steps
=50
)
11)保存模型
model.save
('D:\\smile1\\smiles_and_unsmiles_small_2.h5')
12)在培训和验证数据上绘制模型的损失和准确性(可视化界面)
acc
= history.history
['acc']
val_acc
= history.history
['val_acc']
loss
= history.history
['loss']
val_loss
= history.history
['val_loss']
epochs
= range
(len
(acc
))
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.figure
()
plt.plot
(epochs, loss,
'bo', label
='Training loss')
plt.plot
(epochs, val_loss,
'b', label
='Validation loss')
plt.title
('Training and validation loss')
plt.legend
()
plt.show
()
三、完成一个摄像头采集自己人脸、并对表情(笑脸和非笑脸)的实时分类判读(输出分类文字)的程序;
1.基于上面卷积神经网络的笑脸识别
import cv2
from keras.preprocessing
import image
from keras.models
import load_model
import numpy as np
import dlib
from PIL
import Image
model
= load_model
('D:\\smile1\\smiles_and_unsmiles_small_2.h5')
detector
= dlib.get_frontal_face_detector
()
video
=cv2.VideoCapture
(0
)
font
= cv2.FONT_HERSHEY_SIMPLEX
def rec
(img
):
gray
=cv2.cvtColor
(img,cv2.COLOR_BGR2GRAY
)
dets
=detector
(gray,1
)
if dets is not None:
for face
in dets:
left
=face.left
()
top
=face.top
()
right
=face.right
()
bottom
=face.bottom
()
cv2.rectangle
(img,
(left,top
),
(right,bottom
),
(0,255,0
),2
)
img1
=cv2.resize
(img
[top:bottom,left:right
],dsize
=(150,150
))
img1
=cv2.cvtColor
(img1,cv2.COLOR_BGR2RGB
)
img1
= np.array
(img1
)/255.
img_tensor
= img1.reshape
(-1,150,150,3
)
prediction
=model.predict
(img_tensor
)
if prediction
[0
][0
]>0.5:
result
='unsmile'
else:
result
='smile'
cv2.putText
(img, result,
(left,top
), font, 2,
(0, 255, 0
), 2, cv2.LINE_AA
)
cv2.imshow
('Video', img
)
while video.isOpened
():
res, img_rd
= video.read
()
if not res:
break
rec
(img_rd
)
if cv2.waitKey
(5
) & 0xFF
== ord
('q'):
break
video.release
()
cv2.destroyAllWindows
()
2.基于Dlib的笑脸识别
"""
从视屏中识别人脸,并实时标出面部特征点
"""
import dlib
import numpy as np
import cv2
class face_emotion
():
def __init__
(self
):
self.detector
= dlib.get_frontal_face_detector
()
self.predictor
= dlib.shape_predictor
("E:/shape_predictor_68_face_landmarks.dat")
self.cap
= cv2.VideoCapture
(0
)
self.cap.set
(3, 480
)
self.cnt
= 0
def learning_face
(self
):
line_brow_x
= []
line_brow_y
= []
while (self.cap.isOpened
()):
flag, im_rd
= self.cap.read
()
k
= cv2.waitKey
(1
)
img_gray
= cv2.cvtColor
(im_rd, cv2.COLOR_RGB2GRAY
)
faces
= self.detector
(img_gray, 0
)
font
= cv2.FONT_HERSHEY_SIMPLEX
if (len
(faces
) != 0
):
for i
in range
(len
(faces
)):
for k, d
in enumerate
(faces
):
cv2.rectangle
(im_rd,
(d.left
(), d.top
()),
(d.right
(), d.bottom
()),
(0, 0, 255
))
self.face_width
= d.right
() - d.left
()
shape
= self.predictor
(im_rd, d
)
for i
in range
(68
):
cv2.circle
(im_rd,
(shape.part
(i
).x, shape.part
(i
).y
), 2,
(0, 255, 0
), -1, 8
)
mouth_width
= (shape.part
(54
).x - shape.part
(48
).x
) / self.face_width
mouth_higth
= (shape.part
(66
).y - shape.part
(62
).y
) / self.face_width
brow_sum
= 0
frown_sum
= 0
for j
in range
(17, 21
):
brow_sum +
= (shape.part
(j
).y - d.top
()) +
(shape.part
(j + 5
).y - d.top
())
frown_sum +
= shape.part
(j + 5
).x - shape.part
(j
).x
line_brow_x.append
(shape.part
(j
).x
)
line_brow_y.append
(shape.part
(j
).y
)
tempx
= np.array
(line_brow_x
)
tempy
= np.array
(line_brow_y
)
z1
= np.polyfit
(tempx, tempy, 1
)
self.brow_k
= -round
(z1
[0
], 3
)
brow_hight
= (brow_sum / 10
) / self.face_width
brow_width
= (frown_sum / 5
) / self.face_width
eye_sum
= (shape.part
(41
).y - shape.part
(37
).y + shape.part
(40
).y - shape.part
(38
).y +
shape.part
(47
).y - shape.part
(43
).y + shape.part
(46
).y - shape.part
(44
).y
)
eye_hight
= (eye_sum / 4
) / self.face_width
if round
(mouth_higth
>= 0.03
):
if eye_hight
>= 0.056:
cv2.putText
(im_rd,
"amazing",
(d.left
(), d.bottom
() + 20
), cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255
), 2, 4
)
else:
cv2.putText
(im_rd,
"happy",
(d.left
(), d.bottom
() + 20
), cv2.FONT_HERSHEY_SIMPLEX, 0.8,
(0, 0, 255
), 2, 4
)
else:
if self.brow_k
<= -0.3:
cv2.putText
(im_rd,
"angry",
(d.left
(), d.bottom
() + 20
), cv2.FONT_HERSHEY_SIMPLEX, 0.8,
(0, 0, 255
), 2, 4
)
else:
cv2.putText
(im_rd,
"nature",
(d.left
(), d.bottom
() + 20
), cv2.FONT_HERSHEY_SIMPLEX, 0.8,
(0, 0, 255
), 2, 4
)
cv2.putText
(im_rd,
"Faces: " + str
(len
(faces
)),
(20, 50
), font, 1,
(0, 0, 255
), 1, cv2.LINE_AA
)
else:
cv2.putText
(im_rd,
"No Face",
(20, 50
), font, 1,
(0, 0, 255
), 1, cv2.LINE_AA
)
im_rd
= cv2.putText
(im_rd,
"S: screenshot",
(20, 400
), font, 0.8,
(0, 0, 255
), 1, cv2.LINE_AA
)
im_rd
= cv2.putText
(im_rd,
"Q: quit",
(20, 450
), font, 0.8,
(0, 0, 255
), 1, cv2.LINE_AA
)
if (k
== ord
('s')):
self.cnt +
= 1
cv2.imwrite
("screenshoot" + str
(self.cnt
) +
".jpg", im_rd
)
if (k
== ord
('q')):
break
cv2.imshow
("camera", im_rd
)
self.cap.release
()
cv2.destroyAllWindows
()
if __name__
== "__main__":
my_face
= face_emotion
()
my_face.learning_face
()
注意:这个退出是要检测不到人脸后,按下Q键就可以退出
四、将笑脸数据集换成口罩数据集,完成对口罩佩戴与否的模型训练,采取合适的特征提取方法,重新做上述2-3部。
1.用上述同样的方法修改图片的命名格式
import os
import sys
def rename
():
path
=input
("请输入路径(例如D:\\\\picture):")
name
=input
("请输入开头名:")
startNumber
=input
("请输入开始数:")
fileType
=input
("请输入后缀名(如 .jpg、.txt等等):")
print
("正在生成以"+name+startNumber+fileType+
"迭代的文件名")
count
=0
filelist
=os.listdir
(path
)
for files
in filelist:
Olddir
=os.path.join
(path,files
)
if os.path.isdir
(Olddir
):
continue
Newdir
=os.path.join
(path,name+str
(count+int
(startNumber
))+fileType
)
os.rename
(Olddir,Newdir
)
count+
=1
print
("一共修改了"+str
(count
)+
"个文件")
rename
()
2.卷积网络模型搭建
from keras
import layers
from keras
import models
model
= models.Sequential
()
model.add
(layers.Conv2D
(32,
(3, 3
), activation
='relu',
input_shape
=(150, 150, 3
)))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(64,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Flatten
())
model.add
(layers.Dense
(512, activation
='relu'))
model.add
(layers.Dense
(1, activation
='sigmoid'))
model.summary
()
3.图像生成器读取文件中数据,进行数据预处理。
from keras
import optimizers
model.compile
(loss
='binary_crossentropy',
optimizer
=optimizers.RMSprop
(lr
=1e-4
),
metrics
=['acc'])
from keras.preprocessing.image
import ImageDataGenerator
train_datagen
= ImageDataGenerator
(rescale
=1./255
)
test_datagen
= ImageDataGenerator
(rescale
=1./255
)
train_generator
= train_datagen.flow_from_directory
(
train_dir,
target_size
=(150, 150
),
batch_size
=20,
class_mode
='binary')
validation_generator
= test_datagen.flow_from_directory
(
validation_dir,
target_size
=(150, 150
),
batch_size
=20,
class_mode
='binary')
4.使用数据扩充
datagen
= ImageDataGenerator
(
rotation_range
=40,
width_shift_range
=0.2,
height_shift_range
=0.2,
shear_range
=0.2,
zoom_range
=0.2,
horizontal_flip
=True,
fill_mode
='nearest')
如果我们使用这种数据增强配置训练一个新网络,我们的网络将永远不会看到两次相同的输入。但是,输入它所看到的仍然是高度相关的,因为它们来自于少量的原始图像——我们无法产生新的信息,我们只能重新混合现有的信息。因此,这可能还不足以完全摆脱过度装修。继续战斗过度拟合,我们还将在密连接分类器之前向模型添加一个退出层:
model
= models.Sequential
()
model.add
(layers.Conv2D
(32,
(3, 3
), activation
='relu',
input_shape
=(150, 150, 3
)))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(64,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Conv2D
(128,
(3, 3
), activation
='relu'))
model.add
(layers.MaxPooling2D
((2, 2)))
model.add
(layers.Flatten
())
model.add
(layers.Dropout
(0.5
))
model.add
(layers.Dense
(512, activation
='relu'))
model.add
(layers.Dense
(1, activation
='sigmoid'))
model.compile
(loss
='binary_crossentropy',
optimizer
=optimizers.RMSprop
(lr
=1e-4
),
metrics
=['acc'])
5.使用数据扩充和退出来训练我们的网络
train_datagen
= ImageDataGenerator
(
rescale
=1./255,
rotation_range
=40,
width_shift_range
=0.2,
height_shift_range
=0.2,
shear_range
=0.2,
zoom_range
=0.2,
horizontal_flip
=True,
)
test_datagen
= ImageDataGenerator
(rescale
=1./255
)
train_generator
= train_datagen.flow_from_directory
(
train_dir,
target_size
=(150, 150
),
batch_size
=32,
class_mode
='binary')
validation_generator
= test_datagen.flow_from_directory
(
validation_dir,
target_size
=(150, 150
),
batch_size
=32,
class_mode
='binary')
history = model.fit_generator
(
train_generator,
steps_per_epoch
=100,
epochs
=50,
validation_data
=validation_generator,
validation_steps
=50
)
6.保存模型
model.save
('D:/mask1/masks_and_unmasks_small_2.h5')
7.在培训和验证数据上绘制模型的损失和准确性(可视化界面)
import matplotlib.pyplot as plt
acc
= history.history
['acc']
val_acc
= history.history
['val_acc']
loss
= history.history
['loss']
val_loss
= history.history
['val_loss']
epochs
= range
(len
(acc
))
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.figure
()
plt.plot
(epochs, loss,
'bo', label
='Training loss')
plt.plot
(epochs, val_loss,
'b', label
='Validation loss')
plt.title
('Training and validation loss')
plt.legend
()
plt.show
()
8.实现摄像头口罩识别判断
import cv2
from keras.preprocessing
import image
from keras.models
import load_model
import numpy as np
import dlib
from PIL
import Image
model
= load_model
('D:/mask1/masks_and_unmasks_small_2.h5')
detector
= dlib.get_frontal_face_detector
()
video
=cv2.VideoCapture
(0
)
font
= cv2.FONT_HERSHEY_SIMPLEX
def rec
(img
):
gray
=cv2.cvtColor
(img,cv2.COLOR_BGR2GRAY
)
dets
=detector
(gray,1
)
if dets is not None:
for face
in dets:
left
=face.left
()
top
=face.top
()
right
=face.right
()
bottom
=face.bottom
()
cv2.rectangle
(img,
(left,top
),
(right,bottom
),
(0,255,0
),2
)
img1
=cv2.resize
(img
[top:bottom,left:right
],dsize
=(150,150
))
img1
=cv2.cvtColor
(img1,cv2.COLOR_BGR2RGB
)
img1
= np.array
(img1
)/255.
img_tensor
= img1.reshape
(-1,150,150,3
)
prediction
=model.predict
(img_tensor
)
if prediction
[0
][0
]>0.5:
result
='unmask'
else:
result
='mask'
cv2.putText
(img, result,
(left,top
), font, 2,
(0, 255, 0
), 2, cv2.LINE_AA
)
cv2.imshow
('Video', img
)
while video.isOpened
():
res, img_rd
= video.read
()
if not res:
break
rec
(img_rd
)
if cv2.waitKey
(5
) & 0xFF
== ord
('q'):
break
video.release
()
cv2.destroyAllWindows
()