Python基于keras训练实现微笑识别的示例详解

目录
  • 一、数据预处理
  • 二、训练模型
    • 创建模型
    • 训练模型
    • 训练结果
  • 三、预测
    • 效果
  • 四、源代码
    • pretreatment.py
    • train.py
    • predict.py

一、数据预处理

实验数据来自genki4k

提取含有完整人脸的图片

def init_file():
    num = 0
    bar = tqdm(os.listdir(read_path))
    for file_name in bar:
        bar.desc = "预处理图片: "
        # a图片的全路径
        img_path = (read_path + "/" + file_name)
        # 读入的图片的路径中含非英文
        img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
        # 获取图片的宽高
        img_shape = img.shape
        img_height = img_shape[0]
        img_width = img_shape[1]

        # 用来存储生成的单张人脸的路径

        # dlib检测
        dets = detector(img, 1)
        for k, d in enumerate(dets):
            if len(dets) > 1:
                continue
            num += 1
            # 计算矩形大小
            # (x,y), (宽度width, 高度height)
            # pos_start = tuple([d.left(), d.top()])
            # pos_end = tuple([d.right(), d.bottom()])

            # 计算矩形框大小
            height = d.bottom() - d.top()
            width = d.right() - d.left()

            # 根据人脸大小生成空的图像
            img_blank = np.zeros((height, width, 3), np.uint8)
            for i in range(height):
                if d.top() + i >= img_height:  # 防止越界
                    continue
                for j in range(width):
                    if d.left() + j >= img_width:  # 防止越界
                        continue
                    img_blank[i][j] = img[d.top() + i][d.left() + j]
            img_blank = cv2.resize(img_blank, (200, 200), interpolation=cv2.INTER_CUBIC)
            # 保存图片
            cv2.imencode('.jpg', img_blank)[1].tofile(save_path + "/" + "file" + str(num) + ".jpg")

    logging.info("一共", len(os.listdir(read_path)), "个样本")
    logging.info("有效样本", num)

二、训练模型

创建模型

# 创建网络
def create_model():
    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'])
    return model

训练模型

# 训练模型
def train_model(model):
    # 归一化处理
    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(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=32,
        # Since we use binary_crossentropy loss, we need binary labels
        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=60,
        epochs=12,
        validation_data=validation_generator,
        validation_steps=30)

    # 保存模型
    save_path = "../output/model"
    if not os.path.exists(save_path):
        os.makedirs(save_path)
    model.save(save_path + "/smileDetect.h5")
    return history

训练结果

准确率

丢失率

训练过程

三、预测

通过读取摄像头内容进行预测

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(1) & 0xFF == ord('q'):
        break

效果

四、源代码

pretreatment.py

import dlib  # 人脸识别的库dlib
import numpy as np  # 数据处理的库numpy
import cv2  # 图像处理的库OpenCv
import os
import shutil
from tqdm import tqdm
import logging

# dlib预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('../resources/shape_predictor_68_face_landmarks.dat')
# 原图片路径
read_path = "../resources/genki4k/files"
# 提取人脸存储路径
save_path = "../output/genki4k/files"
if not os.path.exists(save_path):
    os.makedirs(save_path)

# 新的数据集
data_dir = '../resources/data'
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

# 训练集
train_dir = data_dir + "/train"
if not os.path.exists(train_dir):
    os.makedirs(train_dir)
# 验证集
validation_dir = os.path.join(data_dir, 'validation')
if not os.path.exists(validation_dir):
    os.makedirs(validation_dir)
# 测试集
test_dir = os.path.join(data_dir, 'test')
if not os.path.exists(test_dir):
    os.makedirs(test_dir)

# 初始化训练数据
def init_data(file_list):
    # 如果不存在文件夹则新建
    for file_path in file_list:
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        # 存在则清空里面所有数据
        else:
            for i in os.listdir(file_path):
                path = os.path.join(file_path, i)
                if os.path.isfile(path):
                    os.remove(path)

def init_file():
    num = 0
    bar = tqdm(os.listdir(read_path))
    for file_name in bar:
        bar.desc = "预处理图片: "
        # a图片的全路径
        img_path = (read_path + "/" + file_name)
        # 读入的图片的路径中含非英文
        img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
        # 获取图片的宽高
        img_shape = img.shape
        img_height = img_shape[0]
        img_width = img_shape[1]

        # 用来存储生成的单张人脸的路径

        # dlib检测
        dets = detector(img, 1)
        for k, d in enumerate(dets):
            if len(dets) > 1:
                continue
            num += 1
            # 计算矩形大小
            # (x,y), (宽度width, 高度height)
            # pos_start = tuple([d.left(), d.top()])
            # pos_end = tuple([d.right(), d.bottom()])

            # 计算矩形框大小
            height = d.bottom() - d.top()
            width = d.right() - d.left()

            # 根据人脸大小生成空的图像
            img_blank = np.zeros((height, width, 3), np.uint8)
            for i in range(height):
                if d.top() + i >= img_height:  # 防止越界
                    continue
                for j in range(width):
                    if d.left() + j >= img_width:  # 防止越界
                        continue
                    img_blank[i][j] = img[d.top() + i][d.left() + j]
            img_blank = cv2.resize(img_blank, (200, 200), interpolation=cv2.INTER_CUBIC)
            # 保存图片
            cv2.imencode('.jpg', img_blank)[1].tofile(save_path + "/" + "file" + str(num) + ".jpg")

    logging.info("一共", len(os.listdir(read_path)), "个样本")
    logging.info("有效样本", num)

# 划分数据集
def divide_data(file_path, message, begin, end):
    files = ['file{}.jpg'.format(i) for i in range(begin, end)]
    bar = tqdm(files)
    bar.desc = message
    for file in bar:
        src = os.path.join(save_path, file)
        dst = os.path.join(file_path, file)
        shutil.copyfile(src, dst)

if __name__ == "__main__":
    init_file()

    positive_train_dir = os.path.join(train_dir, 'smile')
    negative_train_dir = os.path.join(train_dir, 'unSmile')
    positive_validation_dir = os.path.join(validation_dir, 'smile')
    negative_validation_dir = os.path.join(validation_dir, 'unSmile')
    positive_test_dir = os.path.join(test_dir, 'smile')
    negative_test_dir = os.path.join(test_dir, 'unSmile')
    file_list = [positive_train_dir, positive_validation_dir, positive_test_dir,
                 negative_train_dir, negative_validation_dir, negative_test_dir]

    init_data(file_list)

    divide_data(positive_train_dir, "划分训练集正样本", 1, 1001)
    divide_data(negative_train_dir, "划分训练集负样本", 2200, 3200)
    divide_data(positive_validation_dir, "划分验证集正样本", 1000, 1500)
    divide_data(negative_validation_dir, "划分验证集负样本", 3000, 3500)
    divide_data(positive_test_dir, "划分测试集正样本", 1500, 2000)
    divide_data(negative_test_dir, "划分测试集负样本", 2800, 3500)

train.py

import os
from keras import layers
from keras import models
from tensorflow import optimizers
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator

train_dir = "../resources/data/train"
validation_dir = "../resources/data/validation"

# 创建网络
def create_model():
    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'])
    return model

# 训练模型
def train_model(model):
    # 归一化处理
    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(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=32,
        # Since we use binary_crossentropy loss, we need binary labels
        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=60,
        epochs=12,
        validation_data=validation_generator,
        validation_steps=30)

    # 保存模型
    save_path = "../output/model"
    if not os.path.exists(save_path):
        os.makedirs(save_path)
    model.save(save_path + "/smileDetect.h5")
    return history

# 展示训练结果
def show_results(history):
    # 数据增强过后的训练集与验证集的精确度与损失度的图形
    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()

if __name__ == "__main__":
    model = create_model()

    history = train_model(model)

    show_results(history)

predict.py

import os
from keras import layers
from keras import models
from tensorflow import optimizers
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator

train_dir = "../resources/data/train"
validation_dir = "../resources/data/validation"

# 创建网络
# 检测视频或者摄像头中的人脸
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('../output/model/smileDetect.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(1) & 0xFF == ord('q'):
        break
video.release()
cv2.destroyAllWindows()

以上就是Python基于keras训练实现微笑识别的示例详解的详细内容,更多关于Python keras微笑识别的资料请关注我们其它相关文章!

(0)

相关推荐

  • 基于python+opencv调用电脑摄像头实现实时人脸眼睛以及微笑识别

    本文教大家调用电脑摄像头进行实时人脸+眼睛识别+微笑识别,供大家参考,具体内容如下 一.调用电脑摄像头进行实时人脸+眼睛识别 # 调用电脑摄像头进行实时人脸+眼睛识别,可直接复制粘贴运行 import cv2 face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier(cv2.data.ha

  • Python实现笑脸检测+人脸口罩检测功能

    目录 一.人脸图像特征提取方法 二.对笑脸数据集genki4k进行训练和测试(包括SVM.CNN),输出模型训练精度和测试精度(F1-score和ROC),实现检测图片笑脸和实时视频笑脸检测 (一)环境.数据集准备 (二)训练笑脸数据集genki4k (三)图片笑脸检测 (四)实时视频笑脸检测 三.将笑脸数据集换成人脸口罩数据集,并对口罩数据集进行训练,编写程序实现人脸口罩检测 (一)训练人脸口罩数据集 (二)编程实现人脸口罩检测 一.人脸图像特征提取方法 https://www.jb51.ne

  • Python人脸识别之微笑检测

    目录 一.实验准备 二.图片预处理 三.划分数据集 四.CNN提取人脸识别笑脸和非笑脸 1.创建模型 2.归一化处理 3.数据增强 4.创建网络 5.单张图片测试 6.摄像头实时测试 五.Dlib提取人脸特征识别笑脸和非笑脸 一.实验准备 环境搭建 pip install tensorflow==1.2.0 pip install keras==2.0.6 pip install dlib==19.6.1 pip install h5py==2.10 如果是新建虚拟环境,还需安装以下包 pip

  • Python基于keras训练实现微笑识别的示例详解

    目录 一.数据预处理 二.训练模型 创建模型 训练模型 训练结果 三.预测 效果 四.源代码 pretreatment.py train.py predict.py 一.数据预处理 实验数据来自genki4k 提取含有完整人脸的图片 def init_file():     num = 0     bar = tqdm(os.listdir(read_path))     for file_name in bar:         bar.desc = "预处理图片: "      

  • Python 基于FIR实现Hilbert滤波器求信号包络详解

    在通信领域,可以通过希尔伯特变换求解解析信号,进而求解窄带信号的包络. 实现希尔伯特变换有两种方法,一种是对信号做FFT,单后只保留单边频谱,在做IFFT,我们称之为频域方法:另一种是基于FIR根据传递函数设计一个希尔伯特滤波器,我们称之为时域方法. # -*- coding:utf8 -*- # @TIME : 2019/4/11 18:30 # @Author : SuHao # @File : hilberfilter.py import scipy.signal as signal im

  • Python基于纹理背景和聚类算法实现图像分割详解

    目录 一.基于纹理背景的图像分割 二.基于K-Means聚类算法的区域分割 三.总结 一.基于纹理背景的图像分割 该部分主要讲解基于图像纹理信息(颜色).边界信息(反差)和背景信息的图像分割算法.在OpenCV中,GrabCut算法能够有效地利用纹理信息和边界信息分割背景,提取图像目标物体.该算法是微软研究院基于图像分割和抠图的课题,它能有效地将目标图像分割提取,如图1所示[1]. GrabCut算法原型如下所示: mask, bgdModel, fgdModel = grabCut(img,

  • Python数学建模StatsModels统计回归之线性回归示例详解

    目录 1.背景知识 1.1 插值.拟合.回归和预测 1.2 线性回归 2.Statsmodels 进行线性回归 2.1 导入工具包 2.2 导入样本数据 2.3 建模与拟合 2.4 拟合和统计结果的输出 3.一元线性回归 3.1 一元线性回归 Python 程序: 3.2 一元线性回归 程序运行结果: 4.多元线性回归 4.1 多元线性回归 Python 程序: 4.2 多元线性回归 程序运行结果: 5.附录:回归结果详细说明 1.背景知识 1.1 插值.拟合.回归和预测 插值.拟合.回归和预测

  • python数据可视化使用pyfinance分析证券收益示例详解

    目录 pyfinance简介 pyfinance包含六个模块 returns模块应用实例 收益率计算 CAPM模型相关指标 风险指标 基准比较指标 风险调整收益指标 综合业绩评价指标分析实例 结语 pyfinance简介 在查找如何使用Python实现滚动回归时,发现一个很有用的量化金融包--pyfinance.顾名思义,pyfinance是为投资管理和证券收益分析而构建的Python分析包,主要是对面向定量金融的现有包进行补充,如pyfolio和pandas等. pyfinance包含六个模块

  • Blender Python编程实现程序化建模生成超形示例详解

    目录 正文 什么是超形(Supershapes, Superformula) 二维超形 n1 = n2 = n3 = 1 n1 = n2 = n3 = 0.3 其他特别情况 例子 1 例子 2 例子 3 例子 4 例子 5 奇异的形状 三维超形 Blender 生成超形 详细代码和注释如下 正文 Blender 并不是唯一一款允许你为场景编程和自动化任务的3D软件; 随着每一个新版本的推出,Blender 正逐渐成为一个可靠的 CG 制作一体化解决方案,从使用油脂铅笔的故事板到基于节点的合成.

  • Java实现BP神经网络MNIST手写数字识别的示例详解

    目录 一.神经网络的构建 二.系统架构 服务器 客户端 采用MVC架构 一.神经网络的构建 (1):构建神经网络层次结构 由训练集数据可知,手写输入的数据维数为784维,而对应的输出结果为分别为0-9的10个数字,所以根据训练集的数据可知,在构建的神经网络的输入层的神经元的节点个数为784个,而对应的输出层的神经元个数为10个.隐层可选择单层或多层. (2):确定隐层中的神经元的个数 因为对于隐层的神经元个数的确定目前还没有什么比较完美的解决方案,所以对此经过自己查阅书籍和上网查阅资料,有以下的

  • Python程序包的构建和发布过程示例详解

    关于我 编程界的一名小程序猿,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. 联系:hylinux1024@gmail.com 当我们开发了一个开源项目时,就希望把这个项目打包然后发布到 pypi.org 上,别人就可以通过 pip install 的命令进行安装.本文的教程来自于 Python 官方文档 , 如有不正确的地方欢迎评论拍砖. 0x00 创建项目 本文使用到的项目目录为 ➜ packaging-tuto

  • 对python实现二维函数高次拟合的示例详解

    在参加"数据挖掘"比赛中遇到了关于函数高次拟合的问题,然后就整理了一下源码,以便后期的学习与改进. 在本次"数据挖掘"比赛中感觉收获最大的还是对于神经网络的认识,在接近一周的时间里,研究了进40种神经网络模型,虽然在持续一周的挖掘比赛把自己折磨的惨不忍睹,但是收获颇丰.现在想想也挺欣慰自己在这段时间里接受新知识的能力.关于神经网络方面的理解会在后续博文中补充(刚提交完论文,还没来得及整理),先分享一下高次拟合方面的知识. # coding=utf-8 import

  • 关于Python可视化Dash工具之plotly基本图形示例详解

    Plotly Express是对 Plotly.py 的高级封装,内置了大量实用.现代的绘图模板,用户只需调用简单的API函数,即可快速生成漂亮的互动图表,可满足90%以上的应用场景. 本文借助Plotly Express提供的几个样例库进行散点图.折线图.饼图.柱状图.气泡图.桑基图.玫瑰环图.堆积图.二维面积图.甘特图等基本图形的实现. 代码示例 import plotly.express as px df = px.data.iris() #Index(['sepal_length', '

随机推荐