卷积神经网络实现人脸表情识别

一、实现过程

1.1 下载数据集

https://github.com/truongnmt/smile-detection
创建一个文件夹存放datasets
在这里插入图片描述
1.2 根据猫狗数据集训练的方法来训练笑脸数据集

#coding=gbk
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() 

路径:D:\Face_smile\datasets\train_foder\0

在这里插入图片描述

开始数:0
在这里插入图片描述
unsmile.改为smile.
在这里插入图片描述
在这里插入图片描述

1.2 图片分类

import os, shutil #复制文件
# 原始目录所在的路径
# 数据集未压缩
original_dataset_dir1 = 'D:\\Face_smile\\smile\\datasets\\train_folder\\1'  ##笑脸
original_dataset_dir0 = 'D:\\Face_smile\\smile\\datasets\\train_folder\\0'  ##非笑脸
# 我们将在其中的目录存储较小的数据集
base_dir = 'D:\\Face_smile\\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)

# 将前1000张笑脸图像复制到train_cats_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)

# 将下500张笑脸图像复制到validation_cats_dir
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)
    
# 将下500张笑脸图像复制到test_cats_dir
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)
    
# 将前1000张非笑脸图像复制到train_dogs_dir
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)
    
# 将下500张非笑脸图像复制到validation_dogs_dir
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)
    
# 将下500张非笑脸图像复制到test_dogs_dir
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)

结果如下:
在这里插入图片描述

1.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)))

在这里插入图片描述

1.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()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

1.5 图像生成器读取文件中数据,进行数据预处理

from tensorflow import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])
from keras.preprocessing.image import ImageDataGenerator
# 所有图像将按1/255重新缩放
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 这是目标目录
        train_dir,
        # 所有图像将调整为150x150
        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')

在这里插入图片描述

1.6 开始训练

时间漫长,慢慢等待

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=50)

1
2
3
4
5
6

1.7 保存训练模型

model.save('D:\\Face_smile\\smile1\\smiles_and_unsmiles_small_1.h5')

1.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()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

1.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))

# 将其转换为具有形状的Numpy数组(150、150、3)
x = image.img_to_array(img)

# 把它改成(1150150,3)
x = x.reshape((1,) + x.shape)

# 下面的.flow()命令生成一批随机转换的图像。
# 它将无限循环,所以我们需要在某个时刻“打破”循环!
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'])

1.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,
        # 所有图像将调整为150x150
        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)

1.11保存模型

model.save('D:\\Face——smile\\smile1\\smiles_and_unsmiles_small_2.h5')

1.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()

二、运用训练的模型实现表情识别

2.1 将模型传输到树莓派

将前面训练的模型通过xshell将传输到树莓上,(由于没有摄像头)采用读取图片识别笑脸非笑脸

代码:

# 单张图片进行判断  是笑脸还是非笑脸
import cv2
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import load_model
import numpy as np
#加载模型
model = load_model('smiles_and_unsmiles_small_2.h5')
#本地图片路径
img_path='smile.jpg'
img = image.load_img(img_path, target_size=(150, 150))

img_tensor = image.img_to_array(img)/255.0
img_tensor = np.expand_dims(img_tensor, axis=0)
prediction =model.predict(img_tensor)  
print(prediction)
if prediction[0][0]>0.5:
    result='非笑脸'
else:
    result='笑脸'
print(result)

结果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.2 采用摄像头测试模型

在window上进行

#检测视频或者摄像头中的人脸
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:\Face_smile\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()

结果展示:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CIFAR-10是一个用于图像识别的数据集,其中包含10个类别的50000张32x32的彩色图像。模型使用卷神经网络(CNN)来进行图像识别。CNN通过使用卷层来提取图像的特征,然后使用池化层来减小图像的尺寸,最后使用全连接层来分类图像。这个模型需要训练数据来学习如何将图像分类到正确的类别。 ### 回答2: CIFAR-10卷神经网络模型是用于图像识别的一种常见模型。CIFAR-10是一个广泛使用的图像分类数据集,包含来自十个不同类别的60000个32x32彩色图像。卷神经网络(CNN)是处理图像数据的深度学习模型。 CIFAR-10卷神经网络模型的图像识别过程大致分为以下几个步骤: 1. 输入层:将32x32像素的彩色图像作为输入。 2. 卷层:利用多个卷核对输入图像进行卷操作,提取图像的空间特征。通过卷操作,可以获得图像内部的局部特征,并减少参数的数量。 3. 激活函数:在卷层之后,通过给卷结果应用激活函数,如ReLU函数,增强模型的非线性能力。 4. 池化层:对卷层输出的特征图进行下采样,减少维度并提取图像的重要特征。 5. 全连接层:将池化层的输出展平,并与权重进行矩阵相乘,得到特征向量,然后通过全连接层进行分类操作。 6. 输出层:采用Softmax函数作为激活函数,将最终的特征向量映射为一组概率输出,表示图像属于每个类别的概率。 7. 损失函数:采用交叉熵损失函数,计算实际输出与预测输出的差距,并通过反向传播更新模型参数,提高模型的准确性。 8. 反向传播:通过梯度下降算法,更新每个层的权重和偏置,以最小化损失函数。 9. 输出预测:根据最终的概率输出结果,选择概率最高的类别作为图像的预测标签。 通过不断迭代训练集和测试集,优化模型参数,CIFAR-10卷神经网络模型可以实现对CIFAR-10数据集中图像的准确分类和识别。 ### 回答3: CIFAR-10是一个常用的图像识别数据集,其中包含了10个不同物体类别的图像。卷神经网络(Convolutional Neural Network,CNN)是一种在图像识别任务中表现出色的深度学习模型。下面我将用300字中文为你介绍CIFAR-10卷神经网络模型图像识别。 CIFAR-10卷神经网络模型图像识别任务的目标是根据给定的图像,判断它属于10个不同的类别中的哪一个。这10个类别包括了飞机、汽车、鸟类、猫、鹿、狗、蛙、马、船和卡车。 卷神经网络模型是一种特别适合图像处理任务的神经网络结构。它通过对图像进行多层卷运算和下采样,逐渐提取图像的特征,并最终进行分类。卷操作可以捕捉到图像的局部结构和模式,而下采样操作可以增加模型的鲁棒性和计算效率。 在CIFAR-10图像识别任务中,卷神经网络通常由多个卷层、池化层、全连接层和输出层组成。卷层通过在图像上进行卷操作,提取图像中的特征信息。池化层通过对卷层的输出进行下采样,减少参数数量,并保留重要特征。全连接层接收池化层的输出,并将其转换为最终的分类结果。输出层使用softmax激活函数将分类结果进行概率分布化。 为了提高模型的性能,可以在卷神经网络中使用批归一化、dropout、激活函数等技术。批归一化可以加快模型训练速度、提高模型的鲁棒性,dropout可以减轻过拟合问题,激活函数可以引入非线性,提高模型的表达能力。 CIFAR-10卷神经网络模型图像识别任务是一个非常有挑战性的任务,需要大量的训练样本和计算资源。通过不断优化模型结构、调整超参数和增加训练数据,我们可以提高模型的准确性,并实现更好的图像识别效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值