zoukankan      html  css  js  c++  java
  • 07-人脸识别-人脸矫正

    人脸矫正有几个问题。

    1.歪头:

    2.侧脸:

    3.半边脸:缺失另外半边脸,要寻找其他的解决方案。

    大多数情况下,截取到的人脸是包含歪头和侧脸的现象的。这两个问题,可以同时通过仿射变换来矫正。

    但是要注意,侧脸,是缺少一部分脸部信息的。

    人脸矫正,对歪头的正确度提高有帮助,对侧脸就一般了。

    思路:

    1.之前步骤已经在每张人脸上找到5个特征;

    2.测量 正面脸 的五点对应坐标 pts_dst(这是测量出来的,重要的是5点的位置相对关系);

    3.每张脸的5个点坐标 pts_src,其中的鼻子坐标要设置成和2中鼻子坐标相同,其他坐标点按比例换算;

    4.这两组左边,估计矫正的单应性矩阵(就是仿射变换矩阵,歪脸 to 正脸的变换矩阵);

    5.然后对人脸做仿射变换,得到矫正后的图。

    代码:

    import tensorflow as tf
    import numpy as np
    import cv2
    import detect_face
    import matplotlib.pyplot as plt
    import math
    from scipy import misc
    
    img = misc.imread('001.jpg')
    
    sess = tf.Session()
    pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
    
    # pnet, rnet, onet are 3 funtions
    
    minsize = 20
    threshold = [0.6, 0.7, 0.7]
    factor = 0.709
    df_result, df_points_result = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
    
    # df_points_result is faceNumber X 10
    # need transpose to 10 X faceNumber
    df_points_result = np.transpose(df_points_result)
    
    vec_vec_points = []
    for subPoints in df_points_result:
        # subPoints: [x1,x2,x3,x4,x5,y1,y2,y3,y4,y5]
        # image axis, so convert nose to (48,48)
        # Points of small faces are too close to compute correct Homography Matrix.
        # So, scale points.
        deltaX = 48-subPoints[2]
        deltaY = 48-subPoints[7]
        vec_vec_points.append([[subPoints[0]+deltaX, subPoints[5]+deltaY],
                               [subPoints[1]+deltaX, subPoints[6]+deltaY],
                               [subPoints[2]+deltaX, subPoints[7]+deltaY],
                               [subPoints[3]+deltaX, subPoints[8]+deltaY],
                               [subPoints[4]+deltaX, subPoints[9]+deltaY]])
    
    
    n_face = df_result.shape[0]
    print('detected face number: {}'.format(n_face))
    print(df_result)
    
    plt.figure('faces')
    i = 0
    plt_nrow = n_face / 5
    plt_nrow = plt_nrow + int(n_face != plt_nrow * 5)
    plt_ncol = 5
    crop_face = []
    crop_face_adjust = []
    size_img = (96,96)
    pts_dst = np.array([[29.0,24.0],[67.0,24.0],[48.0,48.0],[28.0,62.0],[68.0,62.0]]) # measure
    for subfaceRec in df_result:
        i = i + 1
        subfaceRec = subfaceRec.astype(int)
        img_a_face = img[subfaceRec[1]:subfaceRec[3], subfaceRec[0]:subfaceRec[2]]
        crop_face.append(img_a_face)
    
        # adjust image
        pts_src = np.array(vec_vec_points[i-1])
        H, _ = cv2.findHomography(pts_src, pts_dst)
        img_a_face_adjust = cv2.warpPerspective(img_a_face, H, (img_a_face.shape[1]+30, img_a_face.shape[0]+30))
        crop_face_adjust.append(img_a_face_adjust)
    
        # resize image
        img_a_face = cv2.resize(img_a_face, size_img, interpolation=cv2.INTER_CUBIC)
    
        # display and show
        print('plt_nrow:{}, plt_ncol:{}, i:{}'.format(plt_nrow, plt_ncol, i))
        plt.subplot(plt_nrow, plt_ncol, i)
        plt.imshow(img_a_face)
    
        cv2.rectangle(img, (subfaceRec[0], subfaceRec[1]), (subfaceRec[2], subfaceRec[3]), (0, 255, 0), 2)
    
    
    # show face adjust
    i = 0
    plt.figure('faces_adjust')
    for sub_img_ad in crop_face_adjust:
        timg = cv2.resize(sub_img_ad, size_img, interpolation=cv2.INTER_CUBIC)
        i = i+1
        plt.subplot(plt_nrow, plt_ncol, i)
        plt.imshow(timg)
    
    # draw points
    plt.figure('img')
    for subPoints in df_points_result:
        # subPoints: [x1,x2,x3,x4,x5,y1,y2,y3,y4,y5]
        cv2.circle(img, (subPoints[0], subPoints[5]), 2, (255, 0, 0), -1) # Red left eye
        cv2.circle(img, (subPoints[1], subPoints[6]), 2, (0, 0, 255), -1) # Blue right eye
        cv2.circle(img, (subPoints[2], subPoints[7]), 2, (0, 255, 0), -1) # Green nose
        cv2.circle(img, (subPoints[3], subPoints[8]), 2, (255, 255, 0), -1) # yellow left mouse
        cv2.circle(img, (subPoints[4], subPoints[9]), 2, (0, 255, 255), -1) # cyan right mouse
    
    plt.imshow(img)
    plt.show()
    
    sess.close()
    

      

    结果:

    问题:

    效果不是很理想,或许只使用旋转矩阵,效果更好吧。

    毕竟侧脸情况,要考虑其他更有效的算法。

    值得一提的是,FaceNet对于输入的人脸,没有矫正的要求。

  • 相关阅读:
    JavaScript 基础,登录前端验证
    CSS实例:图片导航块
    导航,头部,CSS基础
    web基础,用html元素制作web页面
    web基础
    timestamp与timedelta,管理信息系统概念与基础
    datetime处理日期和时间
    Linux操作系统编程 实验五 块设备实验
    Linux操作系统编程 实验四 字符设备实验
    Linux操作系统编程 实验三 模块编程实验
  • 原文地址:https://www.cnblogs.com/alexYuin/p/8870028.html
Copyright © 2011-2022 走看看