Openface(二):实现人脸对齐

最近学习了开源代码Openface,实现了LFW数据集的人脸对齐。这些人脸对齐的图片是后续深度学习神经网络的训练数据集。
代码除了引用常见的python包,还引用了两个本地包:一个是dataset,用以生成图像generator对象和辅助输出;另一个是dlib_align,是上一篇文章中的使用dlib库对齐人脸的包。

本代码将原代码中的parse换为了更为简洁的fire,使用Config类管理对齐函数所需的输入。在实际调用时,只需要在terminal中输入

python align.py alignMain --size=100

即可更新参数。

代码及注释如下:

# align script
# 使用dlib对齐

import cv2
import numpy as np
import os
import sys
import random
import shutil
import fire

# 提取本文件所在目录
fileDir = os.path.dirname(os.path.realpath(__file__))
# 在flidDir同级目录中寻找models文件夹,找到dlib参数的路径
modelDir = os.path.join(fileDir, '..', 'models') 
dlibModelDir = os.path.join(modelDir, 'dlib') #这是存放dilb对齐模板标记点的地方
myfaceDir = os.path.join(modelDir, 'myface') #这是存放一些辅助函数的地方

sys.path.append(os.path.dirname(fileDir)) #为了引用不在同一个文件夹中的包

import align.dataset as dataset
import align.dlib_align as dlib_align

class Config(object):
    inputDir = os.path.join(fileDir, '..', 'Images', 'Raw')
    outputDir = os.path.join(fileDir,'..', 'Images', 'Aligned')
    landmarks = 'outerEyesAndNose'
    dlibFacePredictor = os.path.join(dlibModelDir, 'shape_predictor_68_face_landmarks.dat')
    verbose = True
    size = 96
    skipMulti = False
    fallbackLfw = None

opt = Config()

def alignMain(**kwargs):
    for k,v in kwargs.items():
        setattr(opt,k,v)

    dataset.mkdirP(opt.outputDir) # 如果输出文件夹不存在,创建;存在,啥也不干。
    imgs = list(dataset.ImageIterator(opt.inputDir)) #生成读取图像的generator
    random.shuffle(imgs) #随机打乱imgs里的对象
    landmarkMap = {
        'outerEyesAndNose': dlib_align.AlignDlib.OUTER_EYES_AND_NOSE,
        'innerEyesAndBottomLip': dlib_align.AlignDlib.INNER_EYES_AND_BOTTOM_LIP} #把两种对齐方式存成字典,顾名思义,一种是用鼻子和外侧眼角,一种是用内侧眼角和下唇尖
    # 如果输入参数的对齐方式不在预定义的表里,报错
    if opt.landmarks not in landmarkMap:
        raise Exception("Landmarks unrecognized: {} \n Allowed landmarks: \n outerEyesAndNose \n innerEyesAndBottomLip \n".format(opt.landmarks))

    #取出模板标记点的索引
    landmarkIndices = landmarkMap[opt.landmarks]

    alignFace = dlib_align.AlignDlib(opt.dlibFacePredictor)

    nFallbacks = 0
    for imgObject in imgs:
        print("=== {} ===".format(imgObject.path)) #imgObject.path是Image类的成员
        outDir = os.path.join(opt.outputDir, imgObject.cls) #imgObject.cls是Image类的成员,输出子文件夹名是输出文件夹名加上图片类别的名字
        dataset.mkdirP(outDir) # 如果outDir不存在,创建;存在,啥也不干
        outputPrefix = os.path.join(outDir, imgObject.name) #定义输出图片的文件名,存在刚刚创建的图片类别的文件夹里
        imgName = outputPrefix + ".png" # 定义图片格式,png格式

        if os.path.isfile(imgName):
            if opt.verbose:
                print(" + Already found {}, skipping.".format(imgName))
        else:
            rgb = imgObject.getRGB()
            if rgb is None:
                if opt.verbose:
                    print(" + Unable to load {}".format(imgName))
                outRgb = None
            else:
                outRgb = alignFace.align(opt.size, rgb,
                                          landmark_indices=landmarkIndices,
                                          SkipMulti=opt.skipMulti) #使用对齐函数,截取并对齐图片中的人脸
                if outRgb is None and opt.verbose:
                    print(" + Unable to align {}".format(imgName))
            if opt.fallbackLfw and outRgb is None:
                nFallbacks += 1
                deepFunneled = "{}/{}.jpg".format(os.path.join(opt.fallbackLfw, imgObject.cls), imgObject.name)
                shutil.copy(deepFunneled, "{}/{}.jpg".format(os.path.join(opt.outputDir, imgObject.cls), imgObject.name)) #如果outRgb是空的,并且fallbackLfw不是,那就从fallbackLfw那里复制一份图片到输出图片
            if outRgb is not None:
                if opt.verbose:
                    print(" + Writing aligned file to disk.")
                outBgr = cv2.cvtColor(outRgb, cv2.COLOR_RGB2BGR)
                cv2.imwrite(imgName, outBgr) #把对齐的文件写在输出文件夹里

    if opt.fallbackLfw:
        print('nFallbacks:', nFallbacks)


if __name__ == '__main__':
    fire.Fire()

你可能感兴趣的:(人脸识别)