人脸关键点检测技术:DAN方法详解

DAN(Deep Alignment Network),与以往级联神经网络输入的是图像的某一部分不同,DAN各阶段网络的输入均为整张图片。当网络均采用整张图片作为输入时,DAN可以有效的克服头部姿态以及初始化带来的问题,从而得到更好的检测效果。之所以DAN能将整张图片作为输入,是因为其加入了关键点热图(Landmark Heatmaps),关键点热图的使用是本文的重要创新点。

   注:速度略差,但想法很好。

创新点:

1)与以往的级联模型不同,网络模型输入是整张人脸图,可获取更多信息。

   2)关键点热图。

DAN的基本框架:

这里写图片描述

   迭代处理的框架,可以利用上一帧的预测结果来预测下一帧 Landmark 的位置。
(1)初始

   输入灰度图I以及标准关键点模板 S 0 S{_{0}} S0​,预测得到新的关键点位置 S 1 S{_{1}} S1​。

   注: S 0 S{_{0}} S0​可取所有训练样本的平均关键点。

   其中“FEED FORWARD NN”结构如下,输出136个值用于预测68个关键点:
这里写图片描述

   新的关键点位置会送入 “CONNECTION LAYERS”,该网络结构如下:
这里写图片描述

   首先计算一个 S 1 S{_{1}} S1​到 S 0 S{_{0}} S0​的相似变换矩阵 T 1 T{_{1}} T1​。

   注:这里不采用仿射变换,是为了防止局部畸变,而是采用了相似变换。

   通过 T 1 T{_{1}} T1​我们可以对图像进行矫正得到 T 1 ( I ) T{_{1}}(I) T1​(I),同时对关键点进行变换得到关键点热图 H 1 H{_{1}} H1​。

   特征图 F 1 F{_{1}} F1​是通过“FEED FORWARD NN”的fc1层特征进一步得到的。

   其中关键点热图通过下式计算得到:(其实就是一个中心衰减,关键点处值最大,越远则值越小)。


   其中特征图的计算如下:使用dense layer使fc1层输出单元为3136,使用ReLU激活,reshape为5656,然后上采样到112112,和输入图像一样大。(之所以一开始不直接生成112112,是因为实验发现提升不大但计算量会增大比较多。)目的:人为给CNN增加上一阶段信息。
注:图像的转换使用双线性插值。
(2)初始迭代
每次迭代输入 T N ( I ) T{_{N}}(I) TN​(I), H N H{_{N}} HN​和 F N F{_{N}} FN​,它们的维度均为112
112。然后计算新的 S t + 1 S{_{t+1}} St+1​。

   需要注意的是,由于图像进行了相似变换,因此为了和最初的输入图像相匹配,需要做如下矫正:
这里写图片描述

   IBUG数据集上的第一阶段输出:
这里写图片描述

   从图中发现,DAN要做的“变换”,就是把图片给矫正了。那么DAN对姿态变换具有很好的适应能力,或许就得益于这个“变换”。


实现过程:

数据准备: 扩大1.3倍人脸框裁剪图片,同时计算平均人脸关键点。

   输入图像进行灰度化处理

   网络学习的是已知标准关键点的偏移量。
第一阶段:

   输入灰度图 -> 前向传播 -> 直到fc2层输出136个偏移值,再加上标准的平均关键点来计算损失(L2损失/双眼间距离做归一化)。
第二阶段:

   1)计算相似变换矩阵,根据标准关键点和第一阶段输出的关键点。

   2)对原始图像和第一阶段输出的关键点应用相似变换。

   3)对变换后的输出关键点计算热图

   4) 对第一阶段的fc1层增加一个全连接层,输出为56x56,之后reshape为[None,56,56,1],上采样到112x112大小得到特征图。

   将变换后的原始图像、热图及特征图进行concat连接,作为第二阶段的输入,不断迭代,输出为fc2。

   损失计算:fc2+变换后的关键点来作为最后的预测关键点,因为输入时进行了相似变换,

   因此计算损失时,需要对预测的关键点进行反变换回原图。

   …综上:可以增加N个阶段,每个阶段都需要关键点对齐操作。

热图的计算:

   Python代码:

import os
import numpy as np
import itertools
import cv2
from matplotlib import pyplot as plt
np.set_printoptions(suppress=True,threshold=np.NaN)

HalfSize = 8   #半径的尺寸
IMGSIZE = 112	#图像的尺寸
#定义16*16*2的矩阵,0为y,从上到下[-8,7];1为x,从左到右[-8,7]。
Offsets = np.array(list(itertools.product(range(-HalfSize, HalfSize), \
    range(-HalfSize, HalfSize))), dtype=np.int32).reshape((16,16,2))
#限定landmark的值域范围
def clip_by_value(landmark):
    h,w = landmark.shape
    for i in range(h):
        for j in range(w):
            if landmark[i][j] <HalfSize:
                landmark[i][j] = HalfSize
            if landmark[i][j] > (IMGSIZE-1-HalfSize):
                landmark[i][j] = (IMGSIZE-1-HalfSize)
    return landmark
#针对每个点位,画点热图
def draw_landmark(Point):
    iniLandmark = Point.astype(np.int)	#对点值取整
    locations = Offsets + iniLandmark		#移动16*16区域到关键点区域
    dxdy = Point - iniLandmark.astype(np.float) 		#关键点的偏移量
    offsetsSubPix = Offsets.astype(np.float) - dxdy	#公式中的(x,y)- Si
    vals = 1/(1 + np.linalg.norm(offsetsSubPix,axis =2)) 	#公式H(x,y)
    img = draw_point(locations,vals)
    return img
#在图像上画点
def draw_point(location,vals):
    img = np.zeros((IMGSIZE,IMGSIZE,1),np.float32)
    h,w,c = location.shape
    for i in range(h):
        for j in range(w):
            img[location[i][j][0]][location[i][j][1]] = vals[i][j] 
    return img

if __name__ == '__main__':
    aa = '0.162805  0.337997  0.160961  0.434602  *** *** 0.693376'
    landmark = np.array(aa.strip().split()).astype(np.float32)*112
    land = landmark.reshape((-1,2))[:,::-1]	#reshape成68*2,并进行x和y转换
    land = clip_by_value(land)
    #定义68个点位热图
    R = np.zeros((68,112,112,1)).astype(np.float32)   
    for i in range(68):    
        R[i] = draw_landmark(land[i])
L = np.zeros((112,112)).astype(np.float32)  
#选取68个热图中值最大的进行保留
    for i in range(112):
        for j in range(112):
            maxP = 0
            for k in range(68):
                if maxP < R[k][i][j][:]:
                    maxP = R[k][i][j][:]
            L[i][j] = maxP
    np.save('p2.6.np',L)
    plt.imshow(L)
    plt.show()
    
    #pic = L.reshape((112,112,1))
    #cv2.imshow('aaa',pic)
    #cv2.waitKey(0)

最终的效果:

这里写图片描述

免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空