美文网首页人工智能/模式识别/机器学习精华专题实战
深度学习网络模型部署——人脸检测与表情识别

深度学习网络模型部署——人脸检测与表情识别

作者: 不懂不学不问 | 来源:发表于2020-11-27 11:40 被阅读0次

    实现从项目调研、数据收集、数据预处理、深度卷积神经网络训练再到服务器部署的人脸表情识别小项目

    主要分为两个部分展开:图片检测视频检测
    检测部分分为两个方面:人脸检测表情识别
    先呈上一张效果图(果然,包包越贵越自信hhh): 效果图

    一、数据预处理

    在数据预处理上主要有:

    图像预处理一般有数字化,归一化,几何变化,平滑,复原和增强等步骤。

    在检测边缘前,通常会进行灰度化处理,噪声处理,二值化,开闭运算等。

    二、图片检测

    首先,运行所需要的库:

    import sys
    import numpy as np
    import dlib
    import cv2
    import os
    

    以及所需要的检测68个关键点参数模型:shape_predictor_68_face_landmarks.dat
    链接:https://pan.baidu.com/s/1Xkh17Wdmn9dfx33yA8ghRw
    提取码:rxwh
    人物表情检测参数模型(这个是我自己训练的,准确率有待参考~):my_merge_Xception_0807.61-0.669.hdf5
    链接:https://pan.baidu.com/s/1zviLruPE3wG4BFQhNSJsyA
    提取码:rg3d

    当然你也可以运用自己训练好的模型参数。

    2.1、检测人脸区域,并标上68个点,按区域连线

    导入已经训练好的模型,以及相关变量,人脸表情方面检测主要有7种基本表情:"angry", "disgust", "scared", "happy", "sad", "surprised", "neutral";

    image_file = "image/5.jpg"
    detector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor("face_landmarks/shape_predictor_68_face_landmarks.dat")
    emotion_model_path = 'models/my_merge_Xception_0807.61-0.669.hdf5'
    emotion_classifier = load_model(emotion_model_path, compile=False)
    EMOTIONS = ["angry", "disgust", "scared", "happy", "sad", "surprised", "neutral"]
    

    读取图片并显示:

        image = cv2.imread(image_file)
        cv2.imshow("origin", image)
    

    处理部分,将图片进行resize处理:

    #这个函数里的image就是我们要检测的图片。
    #在人脸检测程序的最后,我们会显示检测的结果图片来验证,这里做resize是为了避免图片过大,超出屏幕范围。
    def resize(image, width=1200):
        r = width * 1.0 / image.shape[1]
        dim = (width, int(image.shape[0] * r))
        resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
        return resized
    

    调用人脸检测模型,在检测之前,作了一个图片灰度处理;

    灰度处理原因:
    1、最直白的原因是,彩色图像单个像素是(R, G, B),转换成灰度图就是(L),简化矩阵, 提高运算速度。

    2、首先,梯度信息对于识别物体来说很重要。所以我们可以把灰度图像看作图像的强度(Intensity),来求一些梯度特征。比较常用的有 HOG,LBP,SIFT等等。如下图为行人检测中的hog模型。通过hog来检测部件,最后找到图像中的行人。(Reference: rbgirshick/voc-dpm)注:可视化为rgb图像,但输入是灰度图像,不要被骗了。

    现行很多算法是需要将彩色图像灰度化再进行处理的。其实你要想明白,灰度化之后失去了什么,又得到了什么。。

    灰度化之后颜色信息丢失,很多color-based算法就不可能这么做,但是很多简单的识别算法对于颜色的依赖性不强,hand-craft特征更多关注边缘梯度信息。工程中很多应用加上color信息之后鲁棒性会下降。灰度化之后矩阵维数下降,运算速度大幅度提高,并且梯度信息仍然保留。就是在performance和efficiency之间做一个权衡罢了。

    链接:https://www.zhihu.com/question/24453478
    来源:知乎

        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        rects = detector(gray, 1)
    

    接着检测问题说,当我检测出一张图片上所有人脸的相关信息(都存储在rects);这时我们可以根据关键点的得到相关人脸区域图片,便于后面表情识别。

    首先,先来看看,如何将每张人脸的关键点标出来(本次是将68个点按区域连接起来的),在检测到的人脸区域中,进一步检测器官(眼睛、鼻子、嘴巴、下巴、眉毛)。

    将相关区域进行划分;

    face_outline = []
            face_eye_left = []
            face_eye_right = []
            face_eyebrow_left = []
            face_eyebrow_right = []
            face_nosepiece = []
            face_nose = []
            face_mouth = []
            face_lip = []
            i = 0
            for (x, y) in shape:
                i = i + 1
                # print(i, x, y)
                if i >= 1 and i <= 17:
                    # print("face_outline")
                    face_outline.append((x, y))
                if i >= 18 and i <= 22:
                    face_eyebrow_left.append((x, y))
                if i >= 23 and i <= 27:
                    face_eyebrow_right.append((x, y))
                if i >= 37 and i <= 42:
                    face_eye_left.append((x, y))
                if i >= 43 and i <= 48:
                    face_eye_right.append((x, y))
                if i >= 28 and i <= 31:
                    face_nosepiece.append((x, y))
                if i >= 32 and i <= 36:
                    face_nose.append((x, y))
                if i >= 49 and i <= 60:
                    face_mouth.append((x, y))
                if i >= 61 and i <= 68:
                    face_lip.append((x, y))
    

    进行关键点之间连线;

    color = (225, 225, 225)
    thickness = 1
    
    def draw_line(image, pixls):
        i = 0
        # print(pixls)
        for x, y in pixls:
            if i < len(pixls)-1:
                next_x, next_y = pixls[i+1]
                cv2.line(image, (x, y), (next_x, next_y), color, thickness)
            # else:
            #     next_x, next_y = pixls[0]
            #     cv2.line(image, (x, y), (next_x, next_y), (225, 225, 225), 2)
            i = i + 1
    
        draw_line(image, face_outline)
        draw_line(image, face_eyebrow_left)
        draw_line(image, face_eyebrow_right)
        draw_line(image, face_eye_left)
        cv2.line(image, face_eye_left[0], face_eye_left[-1], color, thickness)
        draw_line(image, face_eye_right)
        cv2.line(image, face_eye_right[0], face_eye_right[-1], color, thickness)
        draw_line(image, face_nose)
        draw_line(image, face_nosepiece)
        cv2.line(image, face_nose[0], face_nosepiece[-1], color, thickness)
        cv2.line(image, face_nose[-1], face_nosepiece[-1], color, thickness)
        draw_line(image, face_mouth)
        cv2.line(image, face_mouth[0], face_mouth[-1], color, thickness)
        draw_line(image, face_lip)
        cv2.line(image, face_lip[0], face_lip[-1], color, thickness)
    
    示意图: 原图 效果图

    2.2、表情识别

    导入资源包:

    from tensorflow.keras.models import load_model
    from keras.preprocessing.image import img_to_array
    

    dlib脸部特征检测的输出,一个shape里包含了前面说到的脸部特征的68个点

         shape = predictor(gray, rect)
         shape = shape_to_np(shape)
    
    # 这个函数将shape转换成Numpy array,为方便后续处理。
    def shape_to_np(shape, dtype="int"):
        coords = np.zeros((68, 2), dtype=dtype)
        for i in range(0, 68):
                coords[i] = (shape.part(i).x, shape.part(i).y)
        return coords
    

    取出68个关键点中max_left,max_right, max_top, max_bottom,进行裁剪。

         left, right, top, bottom = cope(shape)
         cropped = gray[top:bottom, left:right]  # 裁剪坐标为[y0:y1, x0:x1]
    
    def cope(shape):
        x, y = shape[0]
        min_left = x
        max_right = x
        min_top = y
        max_bottom = y
        for (x, y) in shape:
            if min_left > x:
                min_left = x
            if max_right < x:
                max_right = x
            if min_top > y:
                min_top = y
            if max_bottom < y:
                max_bottom = y
    
        print(min_left,max_right,min_top,max_bottom)
        return min_left, max_right, min_top, max_bottom
    

    将裁剪得到的单通道图像进行预处理,resize,Normalization等。

    def preprocess_input(x, v2=True):
        # 归一化
        x = x.astype('float32')
        x = x / 255.0
        if v2:
            x = x - 0.5
            x = x * 2.0
        return x
    
            roi = cv2.resize(cropped, emotion_classifier.input_shape[1:3])
            roi = preprocess_input(roi)
            roi = img_to_array(roi)
            roi = np.expand_dims(roi, axis=0)
    

    各个表情分类及表情概率。

            # 用模型预测各分类的概率
            preds = emotion_classifier.predict(roi)[0]
            emotion_probability = np.max(preds)  # 最大的概率
            label = EMOTIONS[preds.argmax()]  # 选取最大概率的表情类
    

    圈出人脸区域并显示识别结果。

     cv2.putText(image,
                        "Face{}".format(i + 1) + ", " + label + ": " + str(round(emotion_probability * 100, 2)) + "%",
                        (left - 10, top - 10),
                        cv2.FONT_HERSHEY_TRIPLEX, 0.5, (0, 225, 225), 1)  # putText各参数依次是:图片,添加的
    
    效果图 另外,如果是多个人脸检测,只需要在外层加一个循环就行啦。 多人效果图

    三、视频检测

    视频检测其实就是将视频里面每一帧图片进行检测,其中人脸检测与表情识别都与图片检测方法一样(可以参考上面图片检测)。

    import numpy as np
    import dlib
    import cv2
    
    from tensorflow.keras.models import load_model
    from keras.preprocessing.image import img_to_array
    

    cv2.VideoCapture调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2,也可以为视频路径;

    cap=cv2.VideoCapture("image/7.mp4")
    fps = cap.get(cv2.CAP_PROP_FPS) # 调用cv2方法获取cap的视频帧(帧:每秒多少张图片)
    # 获取cap视频流的每帧大小
    size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
            int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    # 定义编码格式mpge-4
    # 一种视频格式,参数搭配固定,不同的编码格式对应不同的参数
    fourcc = cv2.VideoWriter_fourcc(*"XVID")
    # 定义视频文件输入对象
    outVideo = cv2.VideoWriter("output.avi", fourcc, fps, size) #第一个参数是保存视频文件的绝对路径
    

    读取每一帧图片:

    sucess, image = cap.read()
    
    效果演示: 片段来自于电影《闻香识女人》

    未完待续......

    相关文章

      网友评论

        本文标题:深度学习网络模型部署——人脸检测与表情识别

        本文链接:https://www.haomeiwen.com/subject/wxwviktx.html